【数据结构】排序番外篇 堆,堆排序与其前身选择排序
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了【数据结构】排序番外篇 堆,堆排序与其前身选择排序,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3883字,纯文字阅读大概需要6分钟。
内容图文
![【数据结构】排序番外篇 堆,堆排序与其前身选择排序](/upload/InfoBanner/zyjiaocheng/1046/d33a3a2d768746f9a057d949d231891b.jpg)
堆
优先队列:特殊的”队列”,取出元素的顺序是依照元素的优先权(关键字)大小,而不是元素进入队列的先后顺序
堆是优先队列的完全二叉树表示。
堆的两个特性:
①结构性:用数组表示的完全二叉树
②有序性:任意结点的关键字是其子树所有结点的最大值,叫最大堆(或最小值,叫最小堆)(注意从根结点到任意结点路径上结点序列的有序性)
下面举一个最大堆的例子。
/** 最大堆的操作 */
typedef struct HeapStruct *MaxHeap;
struct HeapStruct {
ElementType *Elements;//存储堆元素的数组int Size;//堆大小int Capacity;//堆的最大容量
};
MaxHeap Create(int MaxSize)
{
/** 创建容量为MaxSize的最大堆 */
MaxHeap H = malloc(sizeof(struct HeapStruct));
H->Elements = malloc((MaxSize+1)*sizeof(ElementType));
H->Size = 0;
H->Capacity = MaxHeap;
H->Elements[0] = MaxData;
/** 定哨兵为大于堆中所有可能元素的值 便于以后的操作 */return H;
}
void Insert(MaxHeap H,ElementType item)
{
/** 将元素item插入最大堆H */int i;
if(IsFull(H)) {
printf("最大堆已满!\n");
return;
}
i = ++H->Size;//i指向插入后堆中的最后一个元素的位置for( ; H->Elements[i/2] > item && i > 1; i /= 2) {
H->Elements[i] = H->Elements[i/2];//向下过滤结点
}
H->Elements[i] = item;//将item插入
}
ElementType DeleteMax(MaxHeap H)
{
/** 从最大堆H中取出键值为最大的元素,并删除一个结点 */int Parent,Child;
ElementType MaxItem,temp;
if(IsEmpty(H)) {
printf("最大堆已空!\n");
return;
}
MaxItem = H->Elements[1];//取出根结点最大值/** 用最大堆中最后一个元素从根节点开始向上过滤下层结点 */
temp = H->Elements[H->Size--];
for(Parent = 1 ; Parent*2 <= H->Size; Parent = Child) {
Child = Parent*2;
if((Child != H->Size) && (H->Elements[Child+1] > H->Elements[Child]))
Child ++;//Child指向左右子结点的较大者if(temp >= H->Elements[Child]) break;
else H->Elements[Parent] = H->Elements[Child];//移动temp元素到下一层
}
H->Elements[Parent] = temp;
return MaxItem;
}
选择排序
选择排序(Selection Sort)的基本思想是:每一趟在n-i+1(i=1,2,…,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。
简单选择排序:没啥好说的,代码如下
void SelectSort(SqList &L)
{
//对顺序表L作简单选择排序for(i = 1 ; i < L.lenth ; ++i) {//选择第i小的记录,并交换到位
j = SelectMinKey(L,i);//选择最小的记录if(i != j) swap(L[i],L[j]);//与第i个记录交换
}
}//SelectSort
树形选择排序:可被堆排序替代,故不再详述
堆排序
先看一种使用堆的简单的O(nlogn)算法
void Heap_Sort(ElementType A[],int N)
{
BuildHeap(A);//建立最小堆for(i = 0 ; i < N ; i ++)
TmpA[i] = DeleteMin(A);//取出堆中最小的元素并返回给TmpAfor(i = 0 ; i < N ; i ++)
A[i] = TmpA[i];//导回原数组
}
真正的堆排序不是建立最小堆而是建立最大堆,每次将最大堆的根和最后一个元素交换,再维护成最大堆,这样直到都交换完毕。代码如下
void Heap_Sort(ElementType A[],int N)
{
/** PercDown(A,a,b)表示在A中考虑前b-1个 把第a个元素下移到该在的位置 */for(i = N/2 ; i >= 0 ; i --)
PercDown(A,i,N);//BuildHeapfor(i = N-1 ; i > 0 ; i --) {
Swap(&A[0],&A[i]);//DeleteMax
PercDown(A,0,i);
}
}
下面来做一个排序实验,将
int s[20] = {11,5,12,6,7,14,20,2,15,3,17,13,1,18,9,4,16,8,10,19};
这组数据分别用简单选择排序和堆排序处理,分别重复一千万次,
结果如下
如果我们把数据加到30个:
这也说明,对于大数据(当然这里只是假设)堆排序是高效的。
下面是实验代码:
#include <cstdio>
#include <ctime>
int main()
{
int t = 10000000;
int start = clock();
while(t--) {
int s[30] = {30,11,29,5,12,6,21,7,23,14,20,22,28,2,15,3,17,13,1,25,18,9,4,16,24,8,10,27,19,26};
for(int i = 0 ; i < 29 ; i ++) {//确定第i个元素int k,mi=31;
for(int j = i ; j < 30 ; j ++) {
if(mi > s[j]) {
mi = s[j];
k = j;
}
}
if(i != k) {
int tmp = s[i];
s[i] = s[k];
s[k] = tmp;
}
}
}/** 简单选择排序 */int _end = clock();
printf("简单选择排序需要%dms\n",_end-start);
t = 10000000;
start = clock();
while(t--) {
int s[30] = {30,11,29,5,12,6,21,7,23,14,20,22,28,2,15,3,17,13,1,25,18,9,4,16,24,8,10,27,19,26};
for(int i = 14; i >= 0 ; i --) {
/** s[i]换到该换的位置上 */int par = i;
for(int child = 2*par+1 ; child < 30 ; child = 2*par+1) {
if(child != 29 && s[child] < s[child+1]) child++;
if(s[par] >= s[child]) break;
else {
int tmp = s[par];
s[par] = s[child];
s[child] = tmp;
}
par = child;
}
}
for(int i = 29 ; i >= 1 ; i --) {
int tmp = s[i];
s[i] = s[0];
s[0] = tmp;
/** 将s[0]换至合适的位置 考虑0-(i-1)元素 */int par = 0;
for(int child = par*2+1; child < i ; child = par*2+1) {
if(child != i-1 && s[child] < s[child+1]) child++;
if(s[par] >= s[child]) break;
else {
int tmp = s[par];
s[par] = s[child];
s[child] = tmp;
}
par = child;
}
}
}/** 堆排序 */
_end = clock();
printf("堆排序需要%dms\n",_end-start);
return0;
}
原文:http://blog.csdn.net/area_52/article/details/43867353
内容总结
以上是互联网集市为您收集整理的【数据结构】排序番外篇 堆,堆排序与其前身选择排序全部内容,希望文章能够帮你解决【数据结构】排序番外篇 堆,堆排序与其前身选择排序所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。