数据结构与C语言实现(四)——树(中):堆的二叉树实现

来源:互联网 发布:java中嵌套循环 编辑:程序博客网 时间:2024/06/01 08:39
#include <stdio.h>#include <stdlib.h>//平衡二叉树 —— AVL树/*1.不平衡的发现者,麻烦节点在发现者右子树的右边,因此叫做RR插入,需要RR旋转(左单旋)2.发现者,麻烦节点是在发现者左子树的左边,叫LL插入,需要LL旋转(右单旋)3.发现者,麻烦节点在左子树的右边,叫LR插入,需要LR旋转*///堆 —— 数组的完全二叉树实现堆/*优先队列:特殊的队列,取出的元素顺序是按照元素的优先权大小而不是元素进入队列的先后顺序 */#define MaxData 65535typedef struct HeapStruct* MaxHeap;struct HeapStruct{int* data;//用于存放堆元素的数组int size;//堆的当前元素个数,下标,类似左儿子右儿子的指针,只不过这里用数组下标实现int capacity;//堆的最大容量};MaxHeap Create(int MaxSize){MaxHeap H = (MaxHeap)malloc(sizeof(struct HeapStruct));//申请二叉树堆的内存地址H->data = (int*)malloc((MaxSize)*sizeof(int));//为存放的数组申请内存空间H->size = 0;//堆指向0H->capacity = MaxSize;H->data[0] =  MaxData;//MaxData是哨兵,大于堆中所有可能的元素的值,便于以后的操作}void InsertH(int X, MaxHeap H){int i;//判断树是否为空if (!H) printf("Error:The tree is not exist");else{H->size++;//当前元素个数 = 下标。现在插入,那么元素+1,同时下标也+1/*插入的核心思路——直到找到比插入值更大的那个节点,不然,就把每一个父节点下移注意!在循环中,data[0]为设定的最大元素,为哨兵。所以在data[0]处一定会出来*/for (i = H->size; H->data[i/2] < X; i /= 2)//1/=2代表父节点的下标。如果父节点小于插入节点,那么循环继续{H->data[i] = H->data[i / 2];//父节点下移一格}H->data[i] = X;//如果一直到哨兵,那就变成整个树的根节点}}//删除最大值操作/*1.首先用数组最后元素代替删除元素2.然后为了满足有序性,需要较大的儿子替换父亲直到没有儿子比父亲大*/int DeleteMax(MaxHeap H){int parent = 1, child;int MaxItem = H->data[1];//取出根节点中的最大值H->data[1] = H->data[H->size];//将数组的最后一个赋值给最大值int temp = H->data[H->size];//将现在最后的值保存,下面就是看这个要放到哪个下标里去H->size--;//元素数量-1H->data[parent] = temp;//把数组最后的节点挪到第一个for (parent = 1; parent * 2 <= H->size; parent = child)// parent * 2 <= H->size,如果左儿子已经在堆栈的外面了,那么就说明没有左儿子//parent = child的意思是,较大的那个儿子变成了新的父节点{child = parent * 2;if ((child != H->size) && (H->data[child] < H->data[child + 1]))child++;//child如果到了H->size说明已经没有了右儿子。判断右儿子如果比左儿子大,那么就选取右儿子当儿子if (temp >= H->data[child]) break;//如果数组末尾值比较大的儿子大,那么说明找到了应该替换的点else{H->data[parent] = H->data[child];//数组末尾值比较大的儿子小,那么儿子上去,爸爸下来}//然后parent = child;较大的儿子节点变成下一次循环要去判断的,从上向下走}H->data[parent] = temp;return MaxItem;}MaxHeap Bulid(MaxHeap H){int parent, child;for (int i = H->size / 2; i > 0; i--){int temp = H->data[i];/****************************************************************************************************************/for (parent = i; parent * 2 <= H->size; parent = child)// parent * 2 <= H->size,如果左儿子已经在堆栈的外面了,那么就说明没有左儿子//parent = child的意思是,较大的那个儿子变成了新的父节点{child = parent * 2;if ((child != H->size) && (H->data[child] < H->data[child + 1]))child++;//child如果到了H->size说明已经没有了右儿子。判断右儿子如果比左儿子大,那么就选取右儿子当儿子if (temp >= H->data[child]) break;//如果数组末尾值比较大的儿子大,那么说明找到了应该替换的点else{H->data[parent] = H->data[child];//数组末尾值比较大的儿子小,那么儿子上去,爸爸下来}//然后parent = child;较大的儿子节点变成下一次循环要去判断的,从上向下走}/****************************************************************************************************************/H->data[parent] = temp;}}

阅读全文
0 0