堆排序
来源:互联网 发布:2016域名价格排行榜 编辑:程序博客网 时间:2024/05/21 17:59
时间复杂度:O(nlgn)空间复杂度:O(1)最关键的问题:创建大根堆
关键:创建大根堆
/*说明:堆排序是完全二叉树顺序存储的应用,存储在数组中。Q1:假设有N个结点进行堆排序,那么存储在数组中的下标是1~N,0下标不使用。 为什么用1~N,而不是用0~N-1下标呢?A1:(1)由父子结点的关系决定的 (2)还有一个重点应用:A[0]在向下调整 函数AdjustDown函数中保存着i的父节点k的值。Q2:AdjustDown(A, i, len)函数每执行一次,至多调整几个值?A2:最初认为最多能调整一个值,其实不然,最多可以调整值的个数是(树高-父节点i所在高度+1)。 AdjustDown(A, i, len)函数在每次调整完一次父节点i的值后,要更新父节点i变成i的子节点, 然后在进行调整判断,...,如此循环往复,直到退出循环。Q3:创建大根堆函数BuildMaxHeap中调用AdjustDown调整函数的调用方向-->是从 第一个父节点到最后一个父节点?还是从最后一个父节点到第一个父节点?A3:根据堆排序创建大根堆过程,可得:调整方向是从最后一个父节点,到第一个父 节点-->因此循环是for(int i=len/2;i>=1;i--)*/#include<stdio.h>/*A[0]: 始终存放着每一次循环的父节点的值k: 始终存放着每一次循环的父节点的下标位置i: 始终存放着k父节点左右结点较大的值for循环的范围是左孩子结点i的范围 for(int i=2*k;i<=len;i*=2)for循环中, 更新父节点更新的是父节点的下标位置*/void AdjustDown(int A[], int k, int len) //k是要调节的父节点{ A[0] = A[k]; //将k父节点的值赋值给A[0],A[0]始终保存着每个父节点的值 //调节是一个循环的过程,因此写个循环 for (int i = 2 * k; i <= len; i *= 2) //i节点初始为父节点k的左孩子 { //在保证有右孩子的基础上,判断k的右孩子是否大于左孩子 if (i+1<=len && A[i] < A[i + 1]) //i+1<=len表示右孩子在数组中,右孩子存在 i++; if (A[i] > A[0]) //如果孩子i大于父节点,进行处理 { A[k] = A[i]; //将左孩子的值赋值给父节点 k = i; //更新左孩子i变成新的父节点,用于下一次循环 } else //若孩子i不大于父节点,则证明下面已经全部符合大根堆要求,直接break出for循环 break; } //执行完所有的for循环调整后,不要忘记把A[0]中存储的最初的父节点A[k]赋值给当前父节点k A[k] = A[0];}void BuildMaxHeap(int A[], int len){ for (int i = len / 2; i >= 1; i--) { AdjustDown(A, i, len); }}int main(){ int A[] = { 0,53,17,78,9,45,65,87,32 }; int length = sizeof(A) / sizeof(A[0]); BuildMaxHeap(A, length); for (int i = 1; i < length; i++) printf("%5d", A[i]); printf("\n");}
堆排序
#include<stdio.h>/*A[0]: 始终存放着每一次循环的父节点的值k: 始终存放着每一次循环的父节点的下标位置i: 始终存放着k父节点左右结点较大的值*/void AdjustDown(int A[], int k, int len) //k是要调节的父节点{ A[0] = A[k]; //将k父节点的值赋值给A[0],A[0]始终保存着每个父节点的值 //调节是一个循环的过程,因此写个循环 for (int i = 2 * k; i <= len; i *= 2) //i节点初始为父节点k的左孩子 { //在保证有右孩子的基础上,判断k的右孩子是否大于左孩子 if (i+1<=len && A[i] < A[i + 1]) //i+1<=len表示右孩子在数组中,右孩子存在 i++; if (A[i] > A[0]) //如果孩子i大于父节点,进行处理 { A[k] = A[i]; //将左孩子的值赋值给父节点 k = i; //更新左孩子i变成新的父节点,用于下一次循环 } else //若孩子i不大于父节点,则证明下面已经全部符合大根堆要求,直接break出for循环 break; } //执行完所有的for循环调整后,不要忘记把A[0]中存储的最初的父节点A[k]赋值给当前父节点k A[k] = A[0];}void BuildMaxHeap(int A[], int len) //创建大根堆{ for (int i = len / 2; i >= 1; i--) { AdjustDown(A, i, len); }}void swap(int &a, int &b){ int t = a; a = b; b = t;}void HeapSort(int A[], int len) //堆排序{ for (int i = 1; i <= len; i++) { BuildMaxHeap(A, len - i + 1); swap(A[1], A[len - i + 1]); }}int main(){ int A[] = { 0,5,17,7,9,5,65,87,32 }; int length = sizeof(A) / sizeof(A[0]); HeapSort(A, length-1); for (int i = 1; i < length; i++) printf("%5d", A[i]); printf("\n");}
堆排序的应用题:
#include<stdio.h>void AdjustDown(int A[], int k, int len) //k是要调节的父节点{ A[0] = A[k]; //将k父节点的值赋值给A[0],A[0]始终保存着每个父节点的值 //调节是一个循环的过程,因此写个循环 for (int i = 2 * k; i <= len; i *= 2) //i节点初始为父节点k的左孩子 { //在保证有右孩子的基础上,判断k的右孩子是否大于左孩子 if (i + 1 <= len && A[i] > A[i + 1]) //i+1<=len表示右孩子在数组中,右孩子存在 i++; if (A[i] < A[0]) //如果孩子i大于父节点,进行处理 { A[k] = A[i]; //将左孩子的值赋值给父节点 k = i; //更新左孩子i变成新的父节点,用于下一次循环 } else //若孩子i不大于父节点,则证明下面已经全部符合大根堆要求,直接break出for循环 break; } //执行完所有的for循环调整后,不要忘记把A[0]中存储的最初的父节点A[k]赋值给当前父节点k A[k] = A[0];}//创建小根堆void BuildMinHeap(int A[], int len) { for (int i = len / 2; i >= 1; i--) { AdjustDown(A, i, len); }}void swap(int &a, int &b){ int t = a; a = b; b = t;}//堆排序void HeapSort(int A[], int len){ for (int i = 1; i <= len; i++) { BuildMinHeap(A, len - i + 1); //printf("%5d", A[1]); swap(A[1], A[len - i + 1]); }}int main(){ int A[] = { 0,2, 1, 4, 3, 6, 5, 8, 7, 10, 9 }; int k = 2; int kk = k; int len = sizeof(A) / sizeof(A[0]) - 1; int *B = new int[len + 1]; for (int i = k, j = 1; k <= len;) //排序1~N-K+1个 { BuildMinHeap(A, 2); B[j++] = A[1]; //printf("%5d", A[1]); A[1] = A[++k]; } //剩下的N-K+2~N个结点用堆排序 A[1] = A[kk]; HeapSort(A, kk-1); for (int i = 1; i <= len; i++) printf("%5d", B[i]); printf("\n");}
阅读全文
1 0
- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 堆与堆排序
- opencv交叉编译arm环境库,静态,动态库和可执行程序
- 虚拟机无法联网的解决办法
- [Struts2] 拦截器和过滤器
- mustache 渲染列表项 index
- java实训第一节
- 堆排序
- [Struts2] 配置Struts可以受理的请求的扩展名
- 由一道题了解Happens
- 动态规划的个人理解
- js窗口尺寸获取常用属性
- [Struts2] 日期类型转换
- 通达OA短信平台,通达OA完美对接中国移动MAS短信平台
- 安卓app开发遇到的问题以及解决方法
- es6 let与constant命令