#include <stdio.h> #include <stdlib.h> #include <math.h> #define Minimum 0 #define Maximum 1 typedef struct Element { int key; int poz; }Element; typedef struct Element* HeapEl; typedef struct Heap { int max_size; int size; HeapEl* heaps; }Heap; Heap* kopiec; void init() //funkcja inicjalizujaca { HeapEl* object; kopiec = (Heap*) malloc(sizeof(Heap)); object = (HeapEl*) malloc(sizeof(HeapEl)); kopiec->size = 0; kopiec->max_size = 1; kopiec->heaps = object; } void zamien(int poz1, int poz2) //funkcja zamieniajaca dwa podane elementy { HeapEl temp_entry; ((kopiec->heaps)[poz1])->poz = poz2; ((kopiec->heaps)[poz2])->poz = poz1; temp_entry = (kopiec->heaps)[poz1]; (kopiec->heaps)[poz1] = (kopiec->heaps)[poz2]; (kopiec->heaps)[poz2] = temp_entry; } void porzadek_dodanie_min(int poz) //funkcja, ktora sprawdza porzadek w kopcu (poziomow Min) po dodaniu wezla { int lvl; int changed=0; int parent = (poz - 1) / 2; //rodzic dla wskazanego wezla (co drugi poziom) - tylko minimum while (poz > 0) { if ( ((kopiec->heaps)[parent]->key < (kopiec->heaps)[poz]->key) && changed==0 ) //Jesli klucz rodzica jest mniejszy niz przekazany klucz to nastepuje zamiana { zamien(poz, parent); poz = parent; lvl=Maximum; } changed = 1; parent = (((poz - 1) / 2)-1)/2; if(lvl==Minimum) //Jesli wezel znajduje sie na poziomie Minimum { if ( ((kopiec->heaps)[parent]->key > (kopiec->heaps)[poz]->key) ) //Jesli klucz rodzica jest wiekszy niz klucz elementu { zamien(poz, parent); //zamieniamy poz = parent; changed = 1; lvl=Minimum; //ustawiamy poziom jako minimum }else{poz=0;} }else { if ( ((kopiec->heaps)[parent]->key < (kopiec->heaps)[poz]->key) && parent!=0 ) //jesli rodzic jest mniejszy niz element i rozny od 0 { zamien(poz, parent); poz = parent; lvl=Maximum; //poziom maximum }else{poz=0;} } } } void porzadek_dodanie_max(int poz) //funkcja sprawdzajaca porzadek w kopcu (porzadek max) { int changed; int lvl; changed=0; int parent = (poz - 1) / 2; while (poz > 0) { if ( ((kopiec->heaps)[parent]->key > (kopiec->heaps)[poz]->key) && changed==0 ) { zamien(poz, parent); poz = parent; lvl=Minimum; } changed = 1; parent = (((poz - 1) / 2)-1)/2; if(lvl==Minimum) { if ( ((kopiec->heaps)[parent]->key > (kopiec->heaps)[poz]->key) ) { zamien(poz, parent); poz = parent; changed = 1; lvl=Minimum; }else{poz=0;} }else{ if ( ((kopiec->heaps)[parent]->key < (kopiec->heaps)[poz]->key) && parent!=0 ) { zamien(poz, parent); poz = parent; lvl=Maximum; }else{poz=0;} } } } void porzadek_dodanie(int poz) //Funkcja porzadkujaca kopiec po dodaniu { int lvl; lvl = (int)floor(log2(poz+1)); if (poz >= kopiec->size) //Jesli przeslana poz jest wieksza od rozmiaru - Error { printf("Blad - przekroczono rozmiar kopca"); return; } if((lvl % 2) == Maximum) //Jesli parzyste to maximum, else minimum { porzadek_dodanie_max(poz); }else { porzadek_dodanie_min(poz); } } //funkcja sprawdzajaca czy na danym poziomie jest mniejsza (wieksza) wartosc int zamienMinMaxOnLvl(int act_ind, int lvl, int type) { int i,start, stop, num, ind, act; act = kopiec->heaps[act_ind]->key; start = 4*act_ind + 3; stop = start + 3; ind = start; if(start > kopiec->size) return -1; num = kopiec->heaps[ind]->key; if(type == Maximum) { if(stop > kopiec->size) stop = kopiec->size; for(i=start; i<=stop; i++ ) { if (kopiec->heaps[i]->key > num) {num = kopiec->heaps[i]->key;ind = i;} } if(act < num) { return ind; }else { return -1; } }else{ if(stop > kopiec->size) stop = kopiec->size; for(i=start; i<=stop; i++ ){ if (kopiec->heaps[i]->key < num) {num = kopiec->heaps[i]->key;ind = i;} } if(act > num){ return ind; }else{ return -1; } } } void porzadek_del_min(int poz) //funkcja porzadkujaca kopiec po odjeciu min { int maxlvl,lvl,right,left, parent, ctr,tmp, smaller; lvl = (int)floor(log2(poz+1)) + 2; //obliczenia poziomu na podstawie pozycji maxlvl = (int)floor(log2(kopiec->size)); ctr=1; while (ctr>0) { if(lvl <= maxlvl) { tmp = zamienMinMaxOnLvl(poz,lvl, Minimum); } else{tmp=-1;} if(tmp>0) { zamien(poz, tmp); poz=tmp; lvl+=2; }else { ctr=-1; } } parent = (poz - 1) / 2; left = 2 * poz + 1; right = left + 1; smaller = right; if (right > kopiec->size - 1){ smaller = left; }else if (((kopiec->heaps)[left])->key < ((kopiec->heaps)[right])->key){ smaller = left; } if ((smaller <= kopiec->size - 1) && (((kopiec->heaps)[smaller])->key < ((kopiec->heaps)[poz])->key) ){ zamien(poz, smaller); poz = smaller; } if(kopiec->heaps[parent]->key < kopiec->heaps[poz]->key) { zamien(poz, parent); } } void porzadek_del_max(int poz) //porzadkujemy kopiec po skasowaniu wezla na poziomie max { int maxlvl,lvl,right,left, parent, ctr,tmp, bigger; lvl = (int)floor(log2(poz+1)) + 2; maxlvl = (int)floor(log2(kopiec->size)); ctr=1; while (ctr>0) { if(lvl <= maxlvl) { tmp = zamienMinMaxOnLvl(poz,lvl, Maximum);} else { tmp=-1; } if(tmp>0){ zamien(poz, tmp); poz=tmp; lvl+=2; }else{ ctr=-1; } } parent = (poz - 1) / 2; left = 2 * poz + 1; right = left + 1; bigger = right; if (right > kopiec->size - 1){ bigger = left; }else if (((kopiec->heaps)[left])->key > ((kopiec->heaps)[right])->key){ bigger = left; } if ((bigger <= kopiec->size - 1) && (((kopiec->heaps)[bigger])->key > ((kopiec->heaps)[poz])->key) ){ zamien(poz, bigger); poz = bigger; } if(kopiec->heaps[parent]->key > kopiec->heaps[poz]->key) { zamien(poz, parent); } } int deleteMin() { int tmp; if (kopiec->size <= 0) { return 0; }else { tmp = ((kopiec->heaps)[0])->key; (kopiec->size)--; zamien(0,kopiec->size); porzadek_del_min(0); return tmp; } } int deleteMax() { int tmp,ind; if (kopiec->size <= 0) { return 0; }else{ if((kopiec->heaps)[1]->key > (kopiec->heaps)[2]->key) { ind=1; } else{ ind=2; } tmp = ((kopiec->heaps)[ind])->key; (kopiec->size)--; zamien(ind,kopiec->size); porzadek_del_max(ind); return tmp; } } void addItem(int key) { HeapEl nowy_element; HeapEl* new_ptr_table; nowy_element = (HeapEl)malloc(sizeof(Element)); nowy_element->key = key; //wstawianie nowego elementu nowy_element->poz = kopiec->size; //na najnizszym poziomie kopca if(kopiec->size == kopiec->max_size) { (kopiec->max_size)*=2; new_ptr_table = (HeapEl *)realloc(kopiec->heaps, (kopiec->max_size)*sizeof(HeapEl)); kopiec->heaps = new_ptr_table; } (kopiec->heaps)[kopiec->size] = nowy_element; (kopiec->size)++; porzadek_dodanie(kopiec->size-1); //uporzadkowanie } void print() { if(kopiec->size > 0) { int i,parent; for(i=0;i < (kopiec->size);i++) { parent = (i - 1) / 2; printf("Parent: %d ",((kopiec->heaps)[parent])->key); printf("Key: %d \n",((kopiec->heaps)[i])->key); } } } int main(int argc, char** argv) { int liczba,x,y; init(); srand(time(0)); // addItem(5); // addItem(10); // addItem(3); // addItem(1); // addItem(2); int i=0; while(i<10000) { liczba = rand()%15000+1; if(liczba>0) { addItem(liczba); i++; } } i=0; while(1) { i++; x=deleteMax(); y=deleteMin(); if(x==0 && y==0) break; printf("Wartosc klucza usuwanego (max) (%d): %d \n",i,x); printf("Wartosc klucza usuwanego (min) (%d): %d \n",i,y); } system("pause"); return 1; }