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 :)