Witam
Zaimplementowalem kopiec wyswietlajacy priorytety i wartosci elementow odpowiednio posortowanych, pozniej usuniecie root'a, wyswietlenie jego wartosci i sprowadzenie kopca do odpowiedniej postaci ale nie jest to takie wazne biorac pod uwage moj problem.
Kod programu:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct S_HeapNode {
struct S_HeapNode *parent, *left, *right;
int priority, level;
char value;
} HeapNode;
class Heap {
public:
Heap(void);
void addNode(int priority, char value);
int extractValue(void);
void print(void);
float rootValue();
private:
void heapify(HeapNode *node);
void shiftDown(HeapNode *node);
HeapNode *root;
};
Heap::Heap(void) {
root = 0;
}
// funkcja zwracajaca ilosc poziomow
int getLevelNum(HeapNode *root) {
int level = 0;
while (root != 0) {
level++;
root = root->left;
}
return level - 1;
}
// funkcja zwracajaca wskaznik do elementu najbardziej wysunietego na lewo na danym poziomie
HeapNode *FindLeftMostNodeAtLevel(HeapNode *node, HeapNode **parent, int level) {
do {
if (node->level == level) {
return node;
}
if (parent != 0) {
*parent = node;
}
node = node->left;
} while (node != 0);
return 0;
}
// funkcja zwracajaca wskaznik do prawego sasiada
HeapNode *getRightNeighbour(HeapNode *node, HeapNode **parentCandidate, int level) {
HeapNode *parent = node->parent;
if (parent == 0) {
return 0;
}
if (parent->right == node) {
return getRightNeighbour(parent, parentCandidate, level);
}
if (parent->right == 0) {
if (parentCandidate != 0) {
*parentCandidate = parent;
}
return 0;
}
return FindLeftMostNodeAtLevel(parent->right, parentCandidate, level);
}
void Heap::print(void) {
HeapNode *node = root;
int level = 0;
while (node != 0) {
// wyswietlamy wszystkie elementy z poziomu
HeapNode *temp = node;
do {
printf("%i(%c)", temp->priority, temp->value);
temp = getRightNeighbour(temp, 0, level);
} while (temp != 0);
// idziemy do pierwszego elementu po lewej na nizszy poziom
node = node->left;
level++;
}
}
void Heap::shiftDown(HeapNode *node) {
HeapNode *switchNode = 0;
if (node->left) {
if (node->left->priority > node->priority) {
switchNode = node->left;
}
}
if (node->right) {
if (node->right->priority > node->priority) {
if (node->right->priority > node->left->priority) {
switchNode = node->right;
}
}
}
if (switchNode != 0) {
// przepisanie wartosci
int temp = node->value;
node->value = switchNode->value;
switchNode->value = temp;
// przepisanie priorytetu
temp = node->priority;
node->priority = switchNode->priority;
switchNode->priority = temp;
shiftDown(switchNode);
}
}
int Heap::extractValue(void) {
if (root == 0) {
return 0;
}
int retValue = root->value;
// kalkulacja pierwszego elementu na ostatnim poziomie
HeapNode *node = root;
HeapNode *temp = root;
while (temp != 0) {
node = temp;
temp = temp->left;
}
// bierzemy ostatni element z poziomu
int levelNum = getLevelNum(root);
do {
temp = node;
} while (node = getRightNeighbour(node, 0, levelNum));
// przepisanie wartosci i priorytetu
if (root != temp) {
root->value = temp->value;
root->priority = temp->priority;
// usuwanie bylego root'a
if (temp->parent->left == temp) {
temp->parent->left = 0;
} else {
temp->parent->right = 0;
}
delete temp;
shiftDown(root);
} else {
delete root;
root = 0;
}
return retValue;
}
void Heap::heapify(HeapNode *node) {
if (node->parent == 0) {
return;
}
while (node->parent->priority < node->priority) {
// przepisanie wartosci
int temp = node->value;
node->value = node->parent->value;
node->parent->value = temp;
// przepisanie priorytetu
temp = node->priority;
node->priority = node->parent->priority;
node->parent->priority = temp;
node = node->parent;
if (node->parent == 0) {
break;
}
}
}
void Heap::addNode(int priority, char value) {
// inicjacja nowego elementu
HeapNode *newNode = new HeapNode;
newNode->priority = priority;
newNode->value = value;
newNode->left = newNode->right = 0;
newNode->parent = 0;
if (root == 0) {
newNode->level = 0;
root = newNode;
return;
}
HeapNode *node = root;
HeapNode *temp = root;
while (temp != 0) {
node = temp;
temp = temp->left;
}
// najbardziej wysuniety element w lewo
HeapNode *mostLeftNode = node;
int levelNum = getLevelNum(root);
int nodePerLevelNum = 1 << levelNum;
int nodePerLevel = 0;
HeapNode *parentCandidate;
do {
nodePerLevel++;
} while (node = getRightNeighbour(node, &parentCandidate, levelNum));
if (nodePerLevel == nodePerLevelNum) {
// drzewo na poziomie levelNum jest kompletne -> dodajemy na nizszym poziomie maxymalnie po lewej
mostLeftNode->left = newNode;
newNode->parent = mostLeftNode;
newNode->level = levelNum + 1;
} else {
// drzewo na poziomie levelNum nie pelne, dodajemy do rodzica nieistniejacego prawego sasiada ostatniego elementu
if (parentCandidate->left != 0) {
parentCandidate->right = newNode;
} else {
parentCandidate->left = newNode;
}
newNode->parent = parentCandidate;
newNode->level = levelNum;
}
heapify(newNode);
}
int main(void) {
Heap heap;
srand(time(NULL));
for(int i=0;i<10000;i++) {
heap.addNode(rand()%100000,rand()%25+97);
}
heap.print();
int value;
value = heap.extractValue();
printf("%c\n\n\n\n\n\n\n\n\n\n", value);
heap.print();
return 0;
}
Problem polega na tym ze po wlaczeniu programu dla np. 100 albo 1000 elementow jest spoko, ale dla 10000 juz sie robia problemy (program nie wyswietla wszystkich elementow i nie da sie sprawdzic czy wartosc usunietego root'a jest prawdziwa, bo nie widac tego roota), elementy wyswietlaja sie pionowo, jak wyswietlam po spacji to jest ok (mieszcza sie w konsolce), kompiluje w VS2005Pro.
Moze zna ktos rozwiazanie tego problemu.
Pozdrawiam
edit: moze jakis zapis do pliku pomoze? ale chce zeby to w konsoli dobrze dzialalo :)