Jak złączyć 2 tablice posortowane niemalejąco w jedn,ą zapisując do tablicy trzeciej.....
dostajemy 2 posortowane, i wynikiem ma być trzecia tablica także posortowana składająca się z 2 poprzednich
Nie wiem jak to zrobić
Iterujesz po obu, kopiując mniejszy element, aż do końca obu tablic. Inkrementujesz tylko wskaźnik tej, z której skopiowałeś.
http://stackoverflow.com/a/19719407
Tutaj zakładają, że tablice mają ten sam rozmiar, ale nie powinno być problemem zmiana, by te początkowe tablice miały różne rozmiary.
zrobiłem ale sie program zawiesza :(
#include <stdio.h>
#define n_1 2
#define n_2 3
void merge(int tab1[], int tab2[], int tab3[], int amount)
{
int amount_t1 = 0, amount_t2 = 0;
int i = 0, j;
while (tab1[i++] != '\0')
++amount_t1;
i = 0;
while (tab2[i++] != '\0')
++amount_t2;
if (amount_t1 > amount_t2) {
for (i = 0; i < amount_t2; ++i)
if (tab1[i] < tab2[i] || tab1[i] == tab2[i])
tab3[i] = tab1[i];
for (i = 0; i + amount_t2 < amount; ++i)
tab3[i] = tab1;
}
else {
for (i = 0; i < amount_t1; ++i)
if (tab1[i] < tab2[i] || tab1[i] == tab2[i])
tab3[i] = tab1[i];
for (i = 0; i + amount_t1 < amount; ++i)
tab3[i] = tab2;
}
for (i = 0; i < 5; ++i)
printf("%d\t", tab3[i]);
}
int main(int argc, char* argv[])
{
int amount = n_1 + n_2;
int tab1[n_1] = { 2, 4 };
int tab2[n_2] = { 1, 3, 7 };
int tab3[n_1 + n_2];
merge(tab1, tab2, tab3, amount);
return 0;
Tablice nie są zakończone zerem. C-stringi są. Musisz przekazać wielkości tablic do funkcji.
no i wykodziłe, mogłem zajrzeć wcześniej do wykładu ;-; ,rozumiem o co chodziło z tymi wskażnikami
No i jest probem, bo działa poprawnie ale nie jak tablice są różnej długości
#include <stdio.h>
#define n_1 3
#define n_2 2
void merge(int tab1[], int tab2[], int tab3[], int n1, int n2)
{
int amount = n1 + n2;
int i = -1;
int *W1 = tab1, *W2 = tab2; //dlaczego jak wpisywałem &tab1 to program się wkurzał ? to jest uzyskanie adresu adresu tablicy?
while (++i < amount) {
if(*W1 == *W2) {
tab3[i] = *W1;
++*W1;
++*W2;
}
if (*W1 > *W2) {
tab3[i] = *W2;
++W2;
}
else {
tab3[i] = *W1;
++W1;
}
}
for (i = 0; i < 5; ++i)
printf("%d\t", tab3[i]);
}
int main(int argc, char* argv[])
{
int amount = n_1 + n_2;
int tab1[n_1] = { 2, 2, 5 };
int tab2[n_2] = { -5, 4 };
int tab3[n_1 + n_2];
merge(tab1, tab2, tab3, n_1, n_2);
return 0;
}
//tutaj musi być warunek az do wyczerpania jakies tablicy ale nie wiem jak to zrobic ->
#include <stdio.h>
#define n_1 3
#define n_2 2
void merge(int tab1[], int tab2[], int tab3[], int n1, int n2)
{
int amount = n1 + n2, end_Ofsmaller;
int i = -1;
int *W1 = tab1, *W2 = tab2, *longer;
if(n1 > n2) end_Ofsmaller = n2;
else end_Ofsmaller = n1;
for( i = 0; i < end_Ofsmaller; ++i) {// tutaj musi być warunek az do wyczerpania jakies tablicy ale nie wiem jak to zrobic
if(*W1 == *W2) {
tab3[i] = *W1;
++*W1;
++*W2;
}
if (*W1 > *W2) {
tab3[i] = *W2;
++W2;
}
else {
tab3[i] = *W1;
++W1;
}
}
if(end_Ofsmaller == n2 )
while (++end_Ofsmaller < amount)
tab3[end_Ofsmaller] = tab1[end_Ofsmaller];
else
while (++end_Ofsmaller < amount)
tab3[end_Ofsmaller] = tab2[end_Ofsmaller];
for (i = 0; i < amount; ++i)
printf("%d\t", tab3[i]);
}
int main(int argc, char* argv[])
{
int amount = n_1 + n_2;
int tab1[n_1] = { 2, 2, 5 };
int tab2[n_2] = { -5, 4 };
int tab3[n_1 + n_2];
merge(tab1, tab2, tab3, n_1, n_2);
return 0;
}
"//dlaczego jak wpisywałem &tab1 to program się wkurzał ? to jest uzyskanie adresu adresu tablicy?" - bo nazwa tablicy to wskaźnik na jej pierwszy element, jak dasz &tab1 to tak jakbyś chciał wyłuskać adres wskaźnika (podwójny wskaźnik).
Jak nie wiesz dlaczego źle złącza ci tablice o różnych rozmiarach to sobie wypisz jakie kolejne wartości przyjmują zmienne pod adresami W1 i W2:
2 -5 (2 > -5)
2 4 ( 2 < 4)
2 4 (2 < 4)
5 4 (5 > 4)
5 2 (5 > 2)
czyli zgodnie z działaniem tego programu wpisze ci do tablicy kolejno: -5, 2, 2, 4, 2.
Jak widać takie porównania nie za bardzo działają dla tablic o różnych rozmiarach.
A czy nie lepiej jest zamiast inicjalizować zmienną iteracyjną int i
jedną dla wszystkich pętli w ten sposób:
int i;
for (i=0; ...){
...
}
for(i=0;...){
...
}
, inicjalizować int i
dla każdej pętli z osobna w ten sposób:
for (int i=0; ....){
...
}
for (int i=0; ....){
...
}
?
Ten drugi "nawyk" wydaje mi się dużo lepszy.
memcpy.
TL;DR
Zjadasz wartości, o tu:
if(*W1 == *W2) {
tab3[i] = *W1;
++*W1;
++*W2;
}
a czyli co? dlaczego zjadam, jak są takie same, czyli np. 4 i 4 to ide dalej w tablicy i wpisuje tylko 1 jedynkę
wynikiem ma być trzecia tablica także posortowana składająca się z 2 poprzednich
Zmieniasz założenia.
#include <iostream>
void scal(int* tab1, int len1, int* tab2, int len2, int* tab3)
{
int *t1, *t2, *t3;
for (t1 = tab1, t2 = tab2, t3 = tab3; len1 || len2;) { // co to jest? o co chodzi z tym for?założenie jest żę len 1 lub len 2, a reszta?
if (len1 && len2) {
if (*t1 < *t2) {
*t3++ = *t1++;
len1--;
}
else {
*t3++ = *t2++;
len2--;
}
}
else if (len1) {
*t3++ = *t1++;
len1--;
}
else if (len2) {
*t3++ = *t2++;
len2--;
}
}
}
void print(int* tab, int len, char* str)
{
std::cout << str << ": [ ";
for (int i = 0; i < len; i++) {
std::cout << tab[i] << " ";
}
std::cout << "]" << std::endl;
}
int main()
{
int t1[] = { 1, 3, 5 };
int t2[] = { 2, 4, 6 };
int t3[6];
scal(t1, 3, t2, 3, t3);
print(t3, 6, (char*)"tab3");
return 0;
}
for (t1 = tab1, t2 = tab2, t3 = tab3; len1 || len2;)
Na początku przypisujesz wartości do t1
, t2
, t3
a potem iterujesz tak długo jak choć jedno z len1
i len2
nie jest zerem.
Zdecydowanie preferuję wersję z trzema pętlami zamiast zbędnego drzewka ifów.
Btw, w C++ od takich rzeczy masz std::merge
.
if (len1 && len2)
oznacza jeśli np. 4 i 4 ?
Obie wartości są konwertowane na bool
za pomocą standardowych konwersji. W skrócie: dla x ≠ 0, będzie to true
, a dla x = 0 będzie to false
. Czyli if(len1 && len2)
wymaga aby obie wartości były niezerowe.
Nie testowałem:
void scal(int* tab1, int len1, int* tab2, int len2, int* tab3)
{
int lenx = len1 < len2 ? len1 : len2;
int *t1 = tab1, *t2 = tab2, *t3 = tab3;
int idx = 0;
while(idx++ < lenx) {
if (*t1 < *t2) {
*t3++ = *t1++;
} else if (*t1 > *t2) {
*t3++ = *t2++;
} else {
*t3++ = *t1++;
*t3++ = *t2++;
}
}
int idx1 = idx;
int idx2 = idx;
while(idx1++ < len1) {
*t3++ = *t1++;
}
while(idx2++ < len2) {
*t3++ = *t2++;
}
}
int lenx = len1 < len2 ? len1, endOFone = len1 : len2, endOFone = len2;
dlaczego nie moga tak zrobić? bardzo mi to porzebne, dla jeden endOFone = len1 działa el jak dołoże drugą po :
to nie działa
Zrobiłem **powinno ** działać, ale program się zawiesza, why?
#include <stdio.h>
#define n_1 3
#define n_2 2
void merge(int tab1[], int tab2[], int tab3[], int len1, int len2)
{
int amount = len1 + len2;
int i ;
int *W1 = tab1, *W2 = tab2, *W3 = tab3;
int lenx = len1 < len2 ? len1 : len2 ;
while(len1 && len2){ //to przez tą pętlę ale nie wiem dlaczego, co jest żle
if(*W1 == *W2) {
*W3++ = *W1++;
*W3++ = *W2++;
--len1;
--len2;
}
if (*W1 > *W2) {
*W3++ = *W2++;
--len2;
}
else {
*W3++ = *W1++;
--len1;
}
}
if( len1 ){
while (len1)
*W3++ = *W1++;
--len1;
}
else{
while (len2)
*W3++ = *W2++;
--len1;
}
for (i = 0; i < amount; ++i)
printf("%d\t", tab3[i]);
}
int main(int argc, char* argv[])
{
int amount = n_1 + n_2;
int tab1[n_1] = { 2, 2, 5 };
int tab2[n_2] = { -5, 4 };
int tab3[n_1 + n_2];
merge(tab1, tab2, tab3, n_1, n_2);
return 0;
}
if( len1 ){
while (len1)
*W3++ = *W1++;
--len1;
}
else{
while (len2)
*W3++ = *W2++;
--len1;
}
po sformatowaniu poprawnym, bez dodawania niezbędnych klamerek:
if (len1) {
while (len1)
*W3++ = *W1++;
--len1;
}
else {
while (len2)
*W3++ = *W2++;
--len1;
}
Inaczej mówiąc: dodaj klamerki.
po zmianie danych program się nie włacza nie wiesz co jest grane?
#include <stdio.h>
#define n_1 2
#define n_2 3
void merge(int tab1[], int tab2[], int tab3[], int len1, int len2)
{
int amount = len1 + len2;
int i ;
int *W1 = tab1, *W2 = tab2, *W3 = tab3;
int lenx = len1 < len2 ? len1 : len2 ;
while(len1 && len2){
if(*W1 == *W2) {
*W3++ = *W1++;
*W3++ = *W2++;
--len1;
--len2;
}
if (*W1 > *W2) {
*W3++ = *W2++;
--len2;
}
else {
*W3++ = *W1++;
--len1;
}
}
if( len1 )
while (len1){
*W3++ = *W1++;
--len1;
}
else
while (len2){
*W3++ = *W2++;
--len1;
}
for (i = 0; i < amount; ++i)
printf("%d\t", tab3[i]);
}
int main(int argc, char* argv[])
{
int amount = n_1 + n_2;
int tab1[n_1] = { 2, 5};
int tab2[n_2] = { -5, 4,9 };
int tab3[n_1 + n_2];
merge(tab1, tab2, tab3, n_1, n_2);
return 0;
}
while (len2){
*W3++ = *W2++;
--len1;
}
Metoda Kopiego-Pejsta strikes again. len1
⟶ len2
. Na przyszłość z debuggera korzystaj sam.
ja nic nie kopiowałem, się tylko pomyliłem, nie zauważyłem, ciągle mi się to zdarza,
a wartośći były złe, bo podałem nieposortowane wartości, uff ,już myślałem że wszsystko będe pisał od nowa,
Dddziękuwa wszystkim :)