堆的TopK问题,优先级序列,堆排序d
2018-02-26 20:34
302 查看
堆的概念:
如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元 素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: Ki <= K2*i+1 且 Ki<= K2*i+2 (Ki >= K2*i+1 且 Ki >= K2*i+2) i = 0,1,2…,则称为小堆(或大堆)。小堆(大堆)中:任一结点的关键码均小于(大于)等于它的左右孩子的关键 码,位于堆顶结点的关键码最小(最大),从根节点到每个结点的路径上数 组元素组成的序列都是递增(递减)的堆存储在下标为0开始的数组中,因此在堆中给定下标为i的结点时
如果i=0,结点i是根节点,没有双亲节点;否则结点i的双亲结点为 结点(i-1)/2
如果2 * i + 1 <= n - 1,则结点i的左孩子为结点2 * i + 1,否则结 点i无左孩子
如果2 * i + 2 <= n - 1,则结点i的右孩子为结点2 * i + 2,否则结 点i无右孩子
堆的创建:
void MakeHeap(Datatype *a,size_t n) { int i=(n-2)/2;//最后一个节点的父亲 for (;i>=0;i--) { AdjustDownS(a,n,i);//向下调整 } } void AdjustDownS(Datatype *a,size_t n,int k)//小堆 { int parent=k; int child=parent*2+1; while (child<n) { if (a[child+1]<a[child] && child+1<n)//俩个孩子选大的 { ++child; } if (a[parent]>a[child])//若父亲大于儿子则交换值 { Datatype tmp=a[parent]; a[parent]=a[child]; a[child]=tmp; parent=child;////// child=parent*2+1;////用依次调整 } else { break; } } }
TopK问题:
首先构建TopK函数:查找最大的前K项 需建立小堆 反之大堆void TopK(Datatype* a, size_t n, size_t k)//找出最大的前K项 { int j; int i=(n-2)/2; for (;i>=0;i--)//找最大的前K项 需要创建小堆 { AdjustDownS(a,n,i); } for (j=k;j<n;j++)//从K后进行比较 { if (a[0]<a[j])//大的进行值替换 { a[0]=a[j]; AdjustDownS(a,k,0);//小堆调整 } } for (j=1;j<=k;j++) { printf("%d ",a[j-1]);//打印最大的前K项 } }
TopK问题测试用例:
void Test1() { int i; Datatype a[]={10,11, 13, 12, 16, 18, 15, 17, 14, 19}; Datatype NArray[1000]; srand(time(0)); for (i = 0; i < 1000; ++i) { NArray[i] = rand()%10000; } NArray[30] = 10001; NArray[350] = 10002; NArray[999] = 10003; NArray[158] = 10004; NArray[334] = 10005; TopK(NArray, 1000, 5); //MakeHeap(a,sizeof(a)/sizeof(a[0])); }
优先级序列问题:
首先创建结构体:typedef int Datatype; typedef struct PriorityQueue { Datatype _a ; size_t _size; }PriorityQueue;
在一个有序的堆里插入一个数 应用向上调整:
void AdjustUp(Datatype *a,int child)//大堆 { int parent=(child-1)/2; while (parent>=0) { if (a[parent]<a[child]) { Datatype tmp=a[parent]; a[parent]=a[child]; a[child]=tmp; child=parent; parent=(child-1)/2; } else { break; } } }
然后是优先级的各种的函数构造:
void PriorityQueueInit(PriorityQueue* q)//优先级初始化 { assert(q); memset(q->_a,0,sizeof(Datatype)); q->_size=0; } void PriorityQueuePush(PriorityQueue* q, Datatype x)//在一个有序的堆里插入 { assert(q); if (q->_size==N) { printf("Priority Queue Full!!!\n"); return; } q->_a[q->_size]=x; q->_size++; AdjustUp(q->_a,q->_size-1);//向上调整大的往上调 } void PriorityQueuePop(PriorityQueue* q)//出堆 最大的优先出 { assert(q); if (q->_size==0) { printf("Priority Queue Empty!!!\n"); return; } q->_a[0]=q->_a[q->_size]; --q->_size; AdjustDownD(q->_a,q->_size,0);//出后 进行大堆调整 } Datatype PriorityQueueTop(PriorityQueue* q) { assert(q); return q->_a[0]; } size_t PriorityQueueSize(PriorityQueue* q) { return q->_size; } size_t PriorityQueueEmpty(PriorityQueue* q) { assert(q); return q->_size>0?1:0; }
优先级测试用例:
void Test2() { PriorityQueue q; PriorityQueueInit(&q); PriorityQueuePush(&q, 5); PriorityQueuePush(&q, 2); PriorityQueuePush(&q, 3); PriorityQueuePush(&q, 7); PriorityQueuePush(&q, 6); PriorityQueuePush(&q, 1); PriorityQueuePush(&q, 4); while (PriorityQueueEmpty(&q) != 0) { printf("%d ", PriorityQueueTop(&q)); PriorityQueuePop(&q); } printf("\n"); }
堆排序问题:
void HeapSort(Datatype* a, size_t n)//升序 堆排序 { int i,j; int tmp; for (i=(n-2)/2;i>=0;i--) { AdjustDownD(a,n,i);//如果要构建升序,则需要建大堆 } for (j=n-1;j>=0;j--)//最大的替换到后边 然后在大堆排序 { tmp=a[0]; a[0]=a[j]; a[j]=tmp; AdjustDownD(a,j,0); } for (i=0;i<n;i++) { printf("%d ",a[i]); } }
堆排序测试用例:
void Test3() { int i; Datatype a[]={10,11, 13, 12, 16, 18, 15, 17, 14, 19}; HeapSort(a,sizeof(a)/sizeof(a[0])); }
相关文章推荐
- Java优先级队列处理topK问题
- 堆的实现及应用(优先级队列,堆排,TopK问题)
- Stall Reservations 贪心+自定义优先级的优先队列(求含不重叠子序列的多个序列最小值问题)
- 堆--优先级队列--topK问题
- Android开发之Service优先级问题
- 最长单增子序列问题
- Hdu 4521 小明系列问题——小明序列【lis 变形】
- SQL server 2005主键序列自动增长问题
- CSS的执行顺序和优先级问题--------Day12
- 最长子序列问题
- 最长递增子序列问题的求解(LIS)
- 最大子序列和问题
- 打印到类阵列的给定序列的所有排列的n皇后问题
- 一个有点意思的SQL问题(连续的序列并且值相同的用区间来体现)
- 序列最大和分割、最大距离、滑动窗口最大值问题
- 最优子序列问题
- 最长单调递增子序列问题
- 最大子序列问题
- 最大子序列问题的解
- 剑指Offer---面试题22:栈的push,pop序列问题