[C] kolejka priorytetowa na kopcu

0

Napisalem taka kolejke na kopcu, mam dwa pytania:

  1. Jak pozbyc sie zmiennej globalnej? (tu za bardzo nie mozna przekazywac tego przy wywolywaniach)
  2. czy tak ma dzialac kolejka i czy dobrze dziala?
#include <stdio.h>
#include <time.h>
#include <limits.h>
#define N 10
//Kolejka priorytetowa na kopcu
int n=-1;
int parent(int i){return i/2;};
int left(int i){if(i==0)return 1; else return 2*i;};
int right(int i){if(i==0)return 2; else return 2*i+1;};
void heapify(int t[], int i);
//void build_heap(int t[]);
//void heapsort(int t[]);

int maximum(int t[]){if (n>=0) return t[0]; else printf("BRAK"); return 0;};
int extract_max(int t[]);
void increase_key(int t[], int i, int key);
void insert(int t[], int key);


int main(){
 srand(time(0));
 int t[N];
 //int i=0;
 
 /*for (i=0;i<N;++i)
 	t[i]=rand()%123;
 for (i=0;i<N;++i)
	printf("%d\t", t[i]);
 
 //heapsort(t);
 
 printf("\n\n\n");
 for (i=0; i<N;++i)
	printf("%d\t", t[i]);*/

 int k;
 printf("1-dodaj element, 2-zwroc max(najwiekszy klucz), 3-zwroc max i go usun, 4-zmien klucz, 0 - koniec\n");
 scanf("%d", &k);
 while (k){ 
 	if (k==1){
		printf("podaj element(klucz)\n");
		int e;
		scanf("%d", &e);
		insert(t,e);
	}
	else if (k==2){
		printf("%d\n", maximum(t));
	}
	else if (k==3){
		printf("%d\n", extract_max(t));
 	}
	else if (k==4){
		int i, w;
		printf("podaj ktory element zaaktualizaowac\n");
		scanf("%d", &i);
		printf("podaj nowa wartosc\n");
		scanf("%d", &w);
		increase_key(t,i,w);
	}
	else 
		break;	

	printf("1-dodaj element, 2-zwroc max(najwiekszy klucz), 3-zwroc max i go usun, 4-zmien klucz, 0 - koniec\n");
        scanf("%d", &k);
	if (k!=1 && k!=2 && k!=3 && k!=4)
	break;
 }

 printf("KONIEC\n");
 

return 0;
}
void heapify(int t[], int i){   
 int largest;
 int l = left(i);
 int r = right(i);
 
 if (l < n && t[l] > t[i])
	largest = l;
 else
	largest = i;

 if (r < n && t[r] > t[largest])
	largest = r;
 
 if (largest != i){
 	int x;
	x=t[i];
	t[i]=t[largest];
	t[largest]=x;
	 
        heapify(t, largest);
 }	
}
////////////////////////////////////////////////////////////////////////
/*void build_heap(int t[]){ 
 int i;
 for (i=N/2; i>=0; --i) //trafia w rodzicow
	heapify(t,i,N);
}*/
////////////////////////////////////////////////////////////////////////
/*void heapsort(int t[]){
 build_heap(t);
 int i;
 int n=N;
 for (i=N-1; i>=1; --i){ //pamietaj zakres tablicy
 	int x=t[0];
	t[0]=t[i];
	t[i]=x;
	
	--n;
	heapify(t,0,n);
 }
}*/
//////////////////////////////////////////////////////////////////////////
int extract_max(int t[]){
 if (n<0){
	printf("KURDE BLAD!!! Kopiec pusty\n");
	return 0;
 }
 int max=t[0];
 t[0]=t[n];
 --n;
 heapify(t,0);
 return max;
}
//////////////////////////////////////////////////////////////////////////
void increase_key(int t[], int i, int key){
 if (i<=n){
 	if (key<t[i])
		printf("nowy klucz jest mniejszy niz aktualny!\n");
	
 	t[i]=key;
 	
 	while (i > 0 && t[parent(i)] < t[i]){
 		int x = t[i];
		t[i]=t[parent(i)];
 		t[parent(i)]=x;

		i=parent(i);
 	}
 }
 else
	printf("BLAD\n");
	
}
///////////////////////////////////////////////////////////////////////////
void insert(int t[], int key){
 ++n;
 if (n<N){
 	t[n]=INT_MIN;
 	increase_key(t,n,key);
 }
 else 
	printf("przepelnienie!\n");
}

0

ok, czyli na moje oko kolejka dziala ok, pisales chyba to z Cormena?

jak pozbyc sie globalnej... hmm bedzie chyba ciezko, ale niech ktos bardziej doswiadczony sie wypowie...

0

Nie wiem, czy dziala Ci ta kolejka, ale chodzi o to, ze wrzucasz element na koniec, a wyciagasz z poczatku i przesowasz do poczatku o jeden, ot cala wilozofia.
Natomiast, jesli chodzi o pozbycie sie zmiennej globalnej to mozesz zdefiniowac sobie strukture:

struct kolej {
  int cos_jak_esp;
  char tab[SIZE];
}

Przesylasz zamiast tablicy, adres struktury i operujesz na tej tablicy poslugujac sie zmienna cos_jak_esp jako indeksem tej tablicy.

Drugi pomysl jaki mam to pozbyc sie w ogóle tej zmiennej i ustawic na poczatku cala tablice na jakas dziwna wartosc i dokladajac jechac w petli do napotkania tej wartosci i w jej miejsce wstawiac nowy element, analogicznie ze zdejmowaniem.
Zdejmujesz pierwsza wartosc rozna od tej dziwnej ;)

0

ok, ale to kolejka priorytetowa, wiec chyb wrzucam dane wartosci, a na przodzie mam najwieksza wartosc

a co do tej zmiennej globalnej, w takim programie mozna ja zostawic, czy tu to jest tez nieeleganckie?

0

Priorytetowa tym sie rozni wlasnie ze masz przypisana relacje, czyli rosnaco lub malejaco, a reszta tak jak mowie.
Co do tego, czy bedzie elegancko czy nie to juz nie wiem, esteta raczej nie jestem, tylko zaproponowalem jak mozna pozbyc sie zmiennej globalnej.

0

no ok, tylko ze chyba wyciagam element z najwiekszym priorytetem?

dzieki za pomoc, przerobie sobie to na ktorys ze sposobow zaproponowanych przez Ciebie

0
#include <stdio.h>
#include <time.h>
#include <limits.h>
#define N 10
#define PARENT i>>1
#define LEFT  i<<1
#define RIGHT (i<<1)+1
//Kolejka priorytetowa na kopcu
//int parent(int i){return i/2;};
//int left(int i){if(i==0)return 1; else return 2*i;};
//int right(int i){if(i==0)return 2; else return 2*i+1;};
void heapify(Kolej* w, int i);
//void build_heap(int t[]);
//void heapsort(int t[]);


int maximum(Kolej *w){if ((w->licz)>=0) return w->t[0]; else printf("BRAK"); return 0;};
int extract_max(Kolej *w);
void increase_key(Kolej *w, int i, int key);
void insert(Kolej *w, int key);

typedef struct Kolej {
  int licz;
  char t[N];
};

int main(){
 //srand(time(0));
 Kolej prio={-1,0};;
 Kolej *w;
 w=&prio;
 

 //int i=0; 
 
 /*for (i=0;i<N;++i)
         t[i]=rand()%123;
 for (i=0;i<N;++i)
        printf("%d\t", t[i]);
 
 //heapsort(t);
 
 printf("\n\n\n");
 for (i=0; i<N;++i)
        printf("%d\t", t[i]);*/

 int k;
 printf("1-dodaj element, 2-zwroc max(najwiekszy klucz), 3-zwroc max i go usun, 4-zmien klucz, 0 - koniec\n");
 scanf("%d", &k);
 while (k){
         if (k==1){
                printf("podaj element(klucz)\n");
                int e;
                scanf("%d", &e);
                insert(&prio,e);
        }
        else if (k==2){
                printf("%d\n", maximum(&prio));
        }
        else if (k==3){
                printf("%d\n", extract_max(&prio));
         }
        else if (k==4){
                int i, w;
                printf("podaj ktory element zaaktualizaowac\n");
                scanf("%d", &i);
                printf("podaj nowa wartosc\n");
                scanf("%d", &w);
                increase_key(&prio,i,w);
        }
        else
                break;       

        printf("1-dodaj element, 2-zwroc max(najwiekszy klucz), 3-zwroc max i go usun, 4-zmien klucz, 0 - koniec\n");
        scanf("%d", &k);
        if (k!=1 && k!=2 && k!=3 && k!=4)
        break;
 }

 printf("KONIEC\n");
 

return 0;
}
void heapify(Kolej *w, int i){   
 int largest;
 int l = LEFT;
 int r = RIGHT;
 
 if (l < w->licz && w->t[l] > w->t[i])
        largest = l;
 else
        largest = i;

 if (r < w->licz && w->t[r] > w->t[largest])
        largest = r;
 
 if (largest != i){
         int x;
         x=w->t[i];
         w->t[i]=w->t[largest];
         w->t[largest]=x;
         
        heapify(&prio, largest);
 }       
}
////////////////////////////////////////////////////////////////////////
/*void build_heap(int t[]){
 int i;
 for (i=N/2; i>=0; --i) //trafia w rodzicow
        heapify(t,i,N);
}*/
////////////////////////////////////////////////////////////////////////
/*void heapsort(int t[]){
 build_heap(t);
 int i;
 int n=N;
 for (i=N-1; i>=1; --i){ //pamietaj zakres tablicy
         int x=t[0];
        t[0]=t[i];
        t[i]=x;
       
        --n;
        heapify(t,0,n);
 }
}*/
//////////////////////////////////////////////////////////////////////////
int extract_max(Kolej *w){
 if (w->licz<0){
        printf("KURDE BLAD!!! Kopiec pusty\n");
        return 0;
 }
 int g=w->licz;
 int max=w->t[0];
 w->t[0]=w->t[g];
 w->licz=w->licz-1;
 heapify(w->t,0);
 return max;
}
//////////////////////////////////////////////////////////////////////////
void increase_key(Kolej *w, int i, int key){
 if (i<=w->licz){
         if (key<w->t[i])
                printf("nowy klucz jest mniejszy niz aktualny!\n");
       
         w->t[i]=key;
         
         while (i > 0 && w->t[PARENT] < w->t[i]){
                 int x = w->t[i];
                 w->t[i]=w->t[PARENT];
                 w->t[PARENT]=x;

                i=PARENT;
         }
 }
 else
        printf("BLAD\n");
       
}
///////////////////////////////////////////////////////////////////////////
void insert(Kolej *w, int key){
 
 int n=w->licz;
 --n;
 if (n<N){
         w->t[n]=INT_MIN;
         increase_key(&prio,n,key);
 }
 else
        printf("przepelnienie!\n");
}
0

kompilator rzuca:

kolejka_priorytetowa.c error: expected ‘)’ before ‘*’ token

pozostale bledy to glownie cos ze wskaznikami z funkcji, ale z tym sobie juz poradze, nie wiem tylko dlaczego rzuca tym na poczatku

0

Masz prototyp funkcji z jednym parametrem typu Kolej, a typ Kolej masz dopiero pozniej zadeklarowany, wiec moze tu lezy przyczyna bledu, ale informacja od kompilatora wskazuje raczej na jakis brak nawiasu, czy srednika, czego nie dostrzegam w okolicach miejsca, o ktorym mowi kompilator.

0

jakims cudem poprawilem xD (sam nie wiem jak)

teraz kompilator rzuca:
kolejka_priorytetowa.c: In function ‘heapify’:
kolejka_priorytetowa.c error: ‘prio’ undeclared (first use in this function)
kolejka_priorytetowa.c error: (Each undeclared identifier is reported only once
kolejka_priorytetowa.c error: for each function it appears in.)
kolejka_priorytetowa.c: In function ‘extract_max’:
kolejka_priorytetowa.c error: ‘prio’ undeclared (first use in this function)
kolejka_priorytetowa.c: In function ‘insert’:
kolejka_priorytetowa.c warning: overflow in implicit constant conversion
kolejka_priorytetowa.c error: ‘prio’ undeclared (first use in this function

w funkcji struktura prio nie jest znana i jak to obejsc teraz bez zmiennych globalnych? (bo mi przychodzi do glowy jedynie globalna deklaracja struktury prio)

#include <stdio.h>
#include <time.h>
#include <limits.h>
#define N 10
#define PARENT i>>1
#define LEFT  i<<1
#define RIGHT (i<<1)+1

typedef struct Kolej {
  int licz;
  char t[N];
} Kolej;

//Kolejka priorytetowa na kopcu

void heapify(Kolej* w, int i);
int maximum(Kolej *w){if ((w->licz)>=0) return w->t[0]; else printf("BRAK"); return 0;};
int extract_max(Kolej *w);
void increase_key(Kolej *w, int i, int key);
void insert(Kolej *w, int key);

int main(){
 
 Kolej prio={-1,0};;
 Kolej *w;
 w=&prio;

 int k;
 printf("1-dodaj element, 2-zwroc max(najwiekszy klucz), 3-zwroc max i go usun, 4-zmien klucz, 0 - koniec\n");
 scanf("%d", &k);
 while (k){
         if (k==1){
                printf("podaj element(klucz)\n");
                int e;
                scanf("%d", &e);
                insert(&prio,e);
        }
        else if (k==2){
                printf("%d\n", maximum(&prio));
        }
        else if (k==3){
                printf("%d\n", extract_max(&prio));
         }
        else if (k==4){
                int i, w;
                printf("podaj ktory element zaaktualizaowac\n");
                scanf("%d", &i);
                printf("podaj nowa wartosc\n");
                scanf("%d", &w);
                increase_key(&prio,i,w);
        }
        else
                break;       

        printf("1-dodaj element, 2-zwroc max(najwiekszy klucz), 3-zwroc max i go usun, 4-zmien klucz, 0 - koniec\n");
        scanf("%d", &k);
        if (k!=1 && k!=2 && k!=3 && k!=4)
        break;
 }

 printf("KONIEC\n");
 

return 0;
}
void heapify(Kolej *w, int i){   
 int largest;
 int l = LEFT;
 int r = RIGHT;
 
 if (l < w->licz && w->t[l] > w->t[i])
        largest = l;
 else
        largest = i;

 if (r < w->licz && w->t[r] > w->t[largest])
        largest = r;
 
 if (largest != i){
         int x;
         x=w->t[i];
         w->t[i]=w->t[largest];
         w->t[largest]=x;
         
        heapify(&prio, largest);
 }       
}
////////////////////////////////////////////////////////////////////////
int extract_max(Kolej *w){
 if (w->licz<0){
        printf("KURDE BLAD!!! Kopiec pusty\n");
        return 0;
 }
 int g=w->licz;
 int max=w->t[0];
 w->t[0]=w->t[g];
 w->licz=w->licz-1;
 heapify(&prio,0);
 return max;
}
//////////////////////////////////////////////////////////////////////////
void increase_key(Kolej *w, int i, int key){
 if (i<=w->licz){
         if (key<w->t[i])
                printf("nowy klucz jest mniejszy niz aktualny!\n");
       
         w->t[i]=key;
         
         while (i > 0 && w->t[PARENT] < w->t[i]){
                 int x = w->t[i];
                 w->t[i]=w->t[PARENT];
                 w->t[PARENT]=x;

                i=PARENT;
         }
 }
 else
        printf("BLAD\n");
       
}
///////////////////////////////////////////////////////////////////////////
void insert(Kolej *w, int key){
 
 int n=w->licz;
 --n;
 if (n<N){
         w->t[n]=INT_MIN;
         increase_key(&prio,n,key);
 }
 else
        printf("przepelnienie!\n");
}
0

wpadlem na pomysl, ze mozna w kazdej funkcji napisac:

Kolej kopia= *w przed rekurencyjnym wywolaniem...

ale jest to chyba przekombinowane, a ponadto program sie kompiluje, ale sie sypie... :/

0

Wywolujesz w main funkcje z adresem prio jako pierwszy parametr, ale rekurencyjnie juz wywoluj z parametrem w, a nie prio, poniewaz w danej funkcji to juz w jest wskaznikiem na prio, wiec po co tak kombinowac ?!

0

ok, kompiluje sie, jest tylko 1 warning:

w linijce: w->t[n]=INT_MIN;
kolejka_priorytetowa.c warning: overflow in implicit constant conversion

program jednak sie sypie, nie mozna dodac nowego elementu do kolejki, a po probie 2 wywolania segmentation fault

dzieki za pomoc, teraz postaram sie znalezc bledy w kodzie, bo budowa kodu jest raczej ok

1 użytkowników online, w tym zalogowanych: 0, gości: 1