堆排序简要介绍
来源:互联网 发布:神话特效软件 编辑:程序博客网 时间:2024/05/17 09:35
堆排序
堆是完全二叉树,具有如下性质:大顶堆:每个节点的值大于或等于其左右孩子结点的值,小顶堆:每个节点的值都小于或等于其左右孩子结点的值。
堆排序是根据完全二叉树的性质5来排序的。
完全二叉树性质五:
1.如果i=1,则结点i是二叉树的根,无双亲,如果i>1,则其双亲是结点i/2
2.如果2*i>n,则结点i无左孩子,否则其左孩子是结点2*i
3.如果2*i+1>n,则该结点i无右孩子,否则其右孩子是结点2*i+1
堆排序的思想是,将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点,将它移走,此时末尾元素就是最大值,然后将剩下的n-1个序列重新构造成一个堆,这样就会得到n个元素中的次大值,如此反复,便能得到一个有序序列了。
程序思路:
1.将无序序列构建一个大顶堆。
2.将第一个元素和最后一个元素交换,将前n-1个元素重新构建大顶堆
3.循环往复,直到排序完成。
整体代码:
void Heap_sort(sqlist* l){ assert(l!=NULL); int i; for(i=l->length/2;i>0;--i) { Heap(l,i,l->length); } for(i=l->length;i>1;--i) { swap(l,1,i); Heap(l,1,i-1); }
构建大顶堆代码
void Heap(sqlist* l,int fi,int la){ int tmep,i; temp=l->data[fi]; for( i=fi*2;i<la;i*=2) { if(i<la&&l->data[i]<l->data[i+1]) { ++i; } if(temp>l->data[j]) { break; } l->data[fi]=l->data[i]; fi=j; } l->data[fi]=temp;}
大顶堆代码解释:
1.输入参数为链表,起始位置,结束位置(一般为链表长队或顺序表长度)。
2.循环开始是从起始位置的左孩子开始,判断左右孩子哪个大,找到最大,用最大值和其父节点进行比较。
3.若孩子结点大,将该孩子结点的值赋值给双亲结点,并且将最大孩子结点的位置赋值给根节点,令其为根节点,再循环判断该根节点下的最大孩子结点。否则,跳出循环。
4.最终,将初始值赋值给交换位置后的点。
注意点:
1.在进行左右孩子结点比较时,一定要确保左右孩子结点存在。即左右孩子的坐标点不能超过链表或者顺序表的长度。
2.在查找下一级的最大/最小结点时,一定要判断该级结点的孩子结点在链表长度范围内。
3.赋值的时候是对最终改变了位置的点赋值。
顺序表的堆排序实现(小顶堆)
#define HeapElem intvoid FilterDown(HeapElem* ar, int pos, int end){ int temp = ar[pos]; int i = pos; int j = 2 * pos + 1; while (j< end) { if (j + 1 <= end && ar[j] > ar[j + 1]) j += 1; if (temp <= ar[j]) break; ar[i] = ar[j]; i = j; j = i * 2 + 1; } ar[i] = temp;}void swap(HeapElem* a, HeapElem* b){ int temp = *a; *a = *b; *b = temp;}void main(){ int arr[10] = { 12, 23, 34, 45, 56, 67, 78, 89, 90, 2 }; int len = sizeof(arr) / sizeof(arr[0]); int pos = 0; while (pos!=(len-1)) { FilterDown(arr, 0, len-1-pos); swap(&arr[0], &arr[len - pos - 1]); ++pos; } for (int i = 0; i < len; ++i) { printf("%4d", arr[i]); }}
注意:这里有一个问题有待解决,2这个数字的排序是错误的,造成它错误的原因为,我们没有首先构造出一个小顶堆,所以它在排序时就发生了错误,所以更改时应该先从数组中间开始,向头部遍历,依次构建出一个小顶堆,再对构造好的小顶堆进行排序。
根据以上结论,我重新构建了一下,但还是没有解决问题!!!
void main(){ int arr[10] = { 12,23, 34, 45, 56, 67, 78, 89, 90,2}; int len = sizeof(arr) / sizeof(arr[0]); int pos = 0; for (int i = len / 2; i > 0; --i) { FilterDown(arr, i, len - 1); } while (pos!=(len-1)) { FilterDown(arr, 0, len-1-pos); swap(&arr[0], &arr[len - pos - 1]); ++pos; } for (int i = 0; i < len; ++i) { printf("%4d", arr[i]); }}
还需要思考,来解决这个问题。
- 堆排序简要介绍
- 堆排序的简要概述
- 简要介绍
- 简要介绍
- 介绍堆排序、希尔排序和快速排序
- 《数据结构与算法分析》第十二章,K-d树,与配对堆简要介绍与实现
- 排序介绍(选择+冒泡+快排+堆排序)
- Java栈和堆简要
- wxwidgets简要介绍
- bsh简要介绍
- W3 Jmail 简要介绍
- Atlas UpdatePanel简要介绍
- Atlas UpdatePanel简要介绍
- Atlas UpdatePanel简要介绍
- 简要AT命令介绍
- Atlas UpdatePanel简要介绍
- wxwidgets简要介绍
- UDP简要介绍
- Spring bean id相同引发的故障
- demo_3. Python的函数嵌套
- nodejs和python 简单爬取百度图片保存在本地
- 编译开关学习
- 二叉树的层次遍历
- 堆排序简要介绍
- 分布式事务解决方案课程概述(一)
- bzoj 1965(快速幂+逆元)
- Java学习笔记(二)--函数、函数重载、数组
- S5PV210启动过程分析
- 层次遍历二叉树以及遍历第K层二叉树
- 深信服 一面 2018 秋招
- stack 实现二叉树的非递归遍历——C语言
- 从零自学Hadoop(12):Hadoop命令中