c++实现最大堆建立(链表结构)和堆排序

来源:互联网 发布:c 面向对象编程流程 编辑:程序博客网 时间:2024/06/03 19:29

  建立最大堆并执行堆排序。


#pragma warning (disable: 4715 4018)#ifndef MAXHEAP_H#define MAXHEAP_H#include<iostream>#include<queue>#include<stack>#include<math.h>class MaxHeapNode//二叉树节点类的定义。{friend void Visit(MaxHeapNode *t);friend class MaxHeap;public://定义构造函数。MaxHeapNode(const int &e){data = e;LeftChild = RightChild = NULL;}private:int data;//节点数据。MaxHeapNode *LeftChild;//左孩子指针。MaxHeapNode *RightChild;//右孩子指针。};//最大堆定义class MaxHeap{friend void Visit(MaxHeapNode *t);public:MaxHeap() { root = NULL; size = 0; };int GetRoot();//根??void Initialize(int a[],int n);//初始化。MaxHeap& Insert(int *a,const int &e,int n);//插入元素void Delete();//删除元素。void HeapSort();void OutPutHeap(){LevelOrder(Visit);};//输出。private:int size;//个数。 MaxHeapNode *root;//根节点。 MaxHeapNode *tail;//最后一个节点。 std::stack<MaxHeapNode*> Stack;//层序遍历将所有节点储存在栈中,将来用于删除节点和堆排序!void LevelOrder(void(*Visit) (MaxHeapNode *u));//层序遍历。};int MaxHeap::GetRoot()//得到根节点数据,用于堆排序。{if (root != NULL)return (root->data);}void MaxHeap::LevelOrder(void(*Visit) (MaxHeapNode *u))//层序遍历。{std::queue<MaxHeapNode*> Q;MaxHeapNode *t = root;while (t){Visit(t);if (t->LeftChild) Q.push(t->LeftChild);if (t->RightChild) Q.push(t->RightChild);if (Q.empty())return;else{t = Q.front();Q.pop();}}}MaxHeap& MaxHeap::Insert(int *a,const int &e,int n)//定义插入。{//首先判断是不是满二叉树//是满二叉树,插入最下一层最左节点。//否则插入只有一个孩子的父节点。MaxHeapNode *Find = root;std::queue<MaxHeapNode*> Inserting;Inserting.push(root);int deep = log(size) / log(2) + 1;//计算树的深度。int RealSize = pow(2, deep);//计算该深度下满二叉树节点数。if (size == RealSize)//是满二叉树。{//找最下一层的最左节点。for (int i = 0; i < deep; ++i)Find = Find->LeftChild;Find = new MaxHeapNode(e);Stack.push(Find);}else{while (1){Find = Inserting.front();Inserting.pop();if (Find->LeftChild == NULL || Find->RightChild == NULL)break;Inserting.push(Find->LeftChild);Inserting.push(Find->RightChild);}if (Find->LeftChild == NULL){Find->LeftChild = new MaxHeapNode(e);Stack.push(Find->LeftChild);}else{Find->RightChild = new MaxHeapNode(e);Stack.push(Find->RightChild);}}++size;//多了一个。//重构!int Mider = 0;std::queue<MaxHeapNode*> QqQ;MaxHeapNode *RrR, *LeL, *RiR;QqQ.push(root);for (int i = 0; i < size; ++i){for (int i = 0; i < QqQ.size(); ++i)QqQ.pop();QqQ.push(root);while (!QqQ.empty()){RrR = QqQ.front();if (RrR->LeftChild == NULL || RrR->RightChild == NULL)//不用再处理。break;QqQ.pop();LeL = RrR->LeftChild;RiR = RrR->RightChild;if (RrR->data < LeL->data)//根元素小于左子树节点,交换。{Mider = RrR->data;RrR->data = LeL->data;LeL->data = Mider;}if (RrR->data < RiR->data)//根节点小于右子树,交换。{Mider = RrR->data;RrR->data = RiR->data;RiR->data = Mider;}QqQ.push(LeL);//左、右子树入队。QqQ.push(RiR);}}return *this;}void MaxHeap::Initialize(int a[],int n)//定义初始化。{size = n;std::queue<MaxHeapNode*> Q;//用于插入节点。MaxHeapNode *l, *r, *rr;l = NULL; r = NULL;root = new MaxHeapNode(a[0]);Q.push(root);int index = 1;while (true)//构建二叉树!此时不是最大堆。{if (index >= n)break;rr = Q.front();Q.pop();rr->LeftChild = new MaxHeapNode(a[index]);l = rr->LeftChild;Q.push(l);++index;if (index >= n)break;rr->RightChild = new MaxHeapNode(a[index]);r = rr->RightChild;Q.push(r);++index;if (index >= n)break;}//重构堆:int Mid = 0;std::queue<MaxHeapNode*> QQ;MaxHeapNode *RR, *L, *R;QQ.push(root);for (int i = 0; i < size; ++i){for (int i = 0; i < QQ.size(); ++i)QQ.pop();QQ.push(root);while (!QQ.empty()){RR = QQ.front();if (RR->LeftChild == NULL && RR->RightChild == NULL)//不用再处理。break;QQ.pop();L = RR->LeftChild;R = RR->RightChild;if (L == NULL)break;elseif (RR->data < L->data) //根元素小于左子树节点,交换。{Mid = RR->data;RR->data = L->data;L->data = Mid;}if (R == NULL)break;elseif (RR->data < R->data)//根节点小于右子树,交换。{Mid = RR->data;RR->data = R->data;R->data = Mid;}QQ.push(L);//左、右子树入队。QQ.push(R);}}//为私有成员Stack添加元素。std::queue<MaxHeapNode*> Get;MaxHeapNode *Gen;Get.push(root);Stack.push(root);int counter = 1;while(1){if (counter >= size)break;Gen = Get.front();Get.pop();Get.push(Gen->LeftChild);Stack.push(Gen->LeftChild);++counter;++if (counter >= size)break;Get.push(Gen->RightChild);Stack.push(Gen->RightChild);++counter;if (counter >= size)break;}}void MaxHeap::Delete()//删除节点,即删除堆的车根,然后重构即可。                                            {MaxHeapNode *T;tail = Stack.top();Stack.pop();//经过以下操作,可以找到tail节点的父节点。std::queue<MaxHeapNode*> Use;Use.push(root);while (1){T = Use.front();Use.pop();if (T->LeftChild == tail || T->RightChild == tail || T->LeftChild == NULL || T->RightChild == NULL)break;Use.push(T->LeftChild);Use.push(T->RightChild);}//交换最后一个节点元素和根节点的值,并删除这一节点。root->data = tail->data;if (T->LeftChild == tail){T->LeftChild = NULL;}else{T->RightChild = NULL;}//重构。int Mid = 0;std::queue<MaxHeapNode*> Qq;MaxHeapNode *Rr, *Le, *Ri;Qq.push(root);for (int i = 0; i < size; ++i){for (int i = 0; i < Qq.size(); ++i)Qq.pop();Qq.push(root);while (!Qq.empty()){Rr = Qq.front();if (Rr->LeftChild == NULL || Rr->RightChild == NULL)//不用再处理。break;Qq.pop();Le = Rr->LeftChild;Ri = Rr->RightChild;if (Rr->data < Le->data)//根元素小于左子树节点,交换。{Mid = Rr->data;Rr->data = Le->data;Le->data = Mid;}if (Rr->data < Ri->data)//根节点小于右子树,交换。{Mid = Rr->data;Rr->data = Ri->data;Ri->data = Mid;}Qq.push(Le);//左、右子树入队。Qq.push(Ri);}}--size;//大小少了一个。//重新初始化私有成员Stack。for (int i = 0; i < size; ++i)//删除原有Stack元素。Stack.pop();std::queue<MaxHeapNode*> Want;MaxHeapNode *RRR;Want.push(root);Stack.push(root);int counter = 1;while (1){if (counter >= size)break;RRR = Want.front();Want.pop();Want.push(RRR->LeftChild);Stack.push(RRR->LeftChild);++counter;if (counter >= size)break;Want.push(RRR->RightChild);Stack.push(RRR->RightChild);++counter;if (counter >= size)break;}}void MaxHeap::HeapSort(){int Count = size;for (int index = 0; index < Count; ++index){std::cout << GetRoot() << " ";Delete();}}void Visit(MaxHeapNode *u){std::cout << u->data << " ";}#endif // !MAXHEAP_H


  当时写的时候对类的编写认识不深,代码中有许多重复。在代码中如果把重构堆的代码实现为私有函数,代码会简介很多。