堆排序算法vb.net 堆排序算法流程图

堆排序是什么

【概念】堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]]

公司主营业务:成都做网站、成都网站制作、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联公司是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联公司推出蟠龙免费做网站回馈大家。

=

A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。

【起源】

1991年的计算机先驱奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德(Robert

W.Floyd)和威廉姆斯(J.Williams)在1964年共同发明了著名的堆排序算法(

Heap

Sort

)。

【简介】

堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。

(1)用大根堆排序的基本思想

先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区

再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key

③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。

……

直到无序区只有一个元素为止。

(2)大根堆排序算法的基本操作:

①建堆,建堆是不断调整堆的过程,从len/2处开始调整,一直到第一个节点,此处len是堆中元素的个数。建堆的过程是线性的过程,从len/2到0处一直调用调整堆的过程,相当于o(h1)+o(h2)…+o(hlen/2)

其中h表示节点的深度,len/2表示节点的个数,这是一个求和的过程,结果是线性的O(n)。

②调整堆:调整堆在构建堆的过程中会用到,而且在堆排序过程中也会用到。利用的思想是比较节点i和它的孩子节点left(i),right(i),选出三者最大(或者最小)者,如果最大(小)值不是节点i而是它的一个孩子节点,那边交互节点i和该节点,然后再调用调整堆过程,这是一个递归的过程。调整堆的过程时间复杂度与堆的深度有关系,是lgn的操作,因为是沿着深度方向进行调整的。

③堆排序:堆排序是利用上面的两个过程来进行的。首先是根据元素构建堆。然后将堆的根节点取出(一般是与最后一个节点进行交换),将前面len-1个节点继续进行堆调整的过程,然后再将根节点取出,这样一直到所有节点都取出。堆排序过程的时间复杂度是O(nlgn)。因为建堆的时间复杂度是O(n)(调用一次);调整堆的时间复杂度是lgn,调用了n-1次,所以堆排序的时间复杂度是O(nlgn)[2]

注意:

①只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。

②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。堆排序和直接选择排序相反:在任何时刻堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止

【特点】

堆排序(HeapSort)是一树形选择排序。堆排序的特点是:在排序过程中,将R[l..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系(参见二叉树的顺序存储结构),在当前无序区中选择关键字最大(或最小)的记录

【算法分析】

堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。

平均性能:O(N*logN)。

其他性能:由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。堆排序是就地排序,辅助空间为O(1)。它是不稳定的排序方法。(排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前

和排序后他们的相对位置不发生变化)。

计算机二级的中的“堆排序法”是怎么排的?

堆排序就是将所有待排序的元素组成一个堆,然后不断弹出堆顶的元素并调用函数维持堆序,直到所有元素均被弹出后,排序完成。被弹出的元素序列即一个有序数列。  

一般做法是这样:

当一个节点被插入时,将该节点放在堆的末尾(这是为了保证堆是完全二叉树)然后将该节点与它的父节点比较,看该节点是否大于(或小于)其父节点,即判断当前的堆是否满足堆序。如果不满足,则将该节点与其父节点交换。

再将该节点与其新的父节点做比较,依此类推,直到该节点不再需要与其父节点交换为止。(即满足堆序时停止)  当一个根节点被弹出(即被从堆中删除)时,将堆最尾部的节点移动到头结点的位置,然后将该节点不断与其子节点比较,如果不符合堆序则交换,直到符合堆序为止。

扩展资料:

堆的操作

堆排序是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

在堆的数据结构中,堆中的最大值总是位于根节点(在优先队列中使用堆的话堆中的最小值位于根节点)。堆中定义以下几种操作:

最大堆调整(Max Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点

创建最大堆(Build Max Heap):将堆中的所有数据重新排序

堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算

参考资料:

百度百科-堆排序

3. 用任意一种编程语言(C/C++/Java/C#/VB.NET)写出任意一种你所知的排序算法(比如:冒泡排序, 归并排

#includestdio.h

#includestdlib.h

void BubbleSort(int a[], const int first, const int last);//冒泡排序

void InsertSort(int a[], const int first, const int last);//插入排序

void SelectSort(int a[], const int first, const int last);//选择排序

void MergeSort(int a[], const int p, const int r);//合并排序

void QuickSort(int a[],const int p,const int r);//快速排序

void ShellSort(int a[],const int p,const int r,const int dlta[],const int t);//希尔排序

void HeapSort(int a[],const int p, int r); //堆排序

void StoogeSort(int a[],const int p,const int r);//Stooge排序(不用)算法复杂度没算清楚

void main()

{

//插入排序算法

int a[11] = {6,4,5,3,2,1};

int dlta[]={9,5,3,2,1};

//BubbleSort(a,0,5);

//InsertSort(a,0,5);

//SelectSort(a,0,5);

//MergeSort(a,0,5);

//QuickSort(a,0,5);

//ShellSort(a,0,5,dlta,5);

HeapSort(a,0,5);

//StoogeSort(a,0,5);

for(int i=0; i=5;i++)

{

printf("%d ",a[i]);

}

}

/************************冒泡排序***********************/

void BubbleSort(int a[], int first, int last)

{

//实现对数组a[]中a[first]到a[last]升序的“冒泡”排序

int i,j,temp;

for(i=first; i=last; i++)

{

for(j=first; j last-i; j++)

{

if(a[j] a[j+1])

{

temp = a[j];

a[j] = a[j+1];

a[j+1] = temp;

}

}

}

}

/************************插入排序***********************/

void InsertSort(int a[], int first, int last)

{

//实现对数组a[]中a[first]到a[last]升序的“插入”排序

//最坏情况为n的平方,,多用于小数组

int i,j,temp;

for(i=first+1; i=last; i++)

{

temp = a[i];

j = i - 1;

while((j = 0) (a[j] temp))

{

a[j+1] = a[j];

j--;

}

a[j+1] = temp;

}

}

/************************选择排序***********************/

void SelectSort(int a[], int first, int last)

{

//实现对数组a[]中a[first]到a[last]升序的“选择”排序

int i, j, temp, num;

for(i=first; ilast; i++)

{

num = i;

for(j=i+1; j=last; j++)

{

if(a[j] a[num])

{

num = j;

}

}

if(i != num)

{

temp = a[num];

a[num] = a[i];

a[i] = temp;

}

}

}

/************************合并排序***********************/

void Merge(int a[],const int p,const int q,const int r)

{

//合并排序算法中的实现合并的子程序

int iLLength,iRLength;

int *L, *R, i, j, k;

iLLength = q - p + 1;

iRLength = r - q;

L = (int *)malloc(iLLength*sizeof(int)); //或者 C++中 new int[iLLength];

R = (int *)malloc(iRLength*sizeof(int)); //或者 C++中 new int[iRLength];

if(L == 0 || R== 0)

{

printf("内存分配失败!!!");

return;

}

for(i=0; iiLLength; i++)

{

L[i] = a[p+i];

}

for(j=0; jiRLength; j++)

{

R[j] = a[q+j+1];

}

i = 0;

j = 0;

for(k=p; k=r; k++)

{

if((iiLLength) (jiRLength) (L[i]=R[j]) || (j == iRLength))

{

a[k] = L[i];

i++;

}

else if(jiRLength)

{

a[k] = R[j];

j++;

}

}

free(R);free(L);

}

void MergeSort(int a[],const int p,const int r)

{

//合并排序算法-主程序

//n*lg(n),系数较小

int q;

if(pr)

{

q = (p+r)/2;

MergeSort(a,p,q);

MergeSort(a,q+1,r);

Merge(a,p,q,r);

}

}

/************************Stooge排序***********************/

void StoogeSort(int a[],const int p,const int r)

{

//Stooge算法

int temp, k;

if(a[p]a[r])

{

temp = a[p];

a[p] = a[r];

a[r] = temp;

}

if((p+1) = r)

{

return;

}

k = (r-p+1)/3;

StoogeSort(a,p,r-k);

StoogeSort(a,p+k,r);

StoogeSort(a,p,r-k);

}

/************************快速排序*********************/

int QuickPartition(int a[],const int p,const int r)

{

//快速排序的(关键)分治过程

int temp, x, i, j;

x = a[r];

i = p - 1;

for(j=p; jr; j++)

{

if(a[j] = x)

{

i = i + 1;

temp = a[i];

a[i] = a[j];

a[j] = temp;

}

}

temp = a[i+1];

a[i+1] = a[r];

a[r] = temp;

return (i+1);

}

/*

void QuickSort(int a[],const int p,const int r)

{

//快速排序算法-主程序

//与下面的“尾递归实现方法”比较,缺点:右边数组的递归不是必须的,增加了运行堆栈深度和调用开销

int q;

if(p r)

{

q = QuickPartition(a, p, r);

QuickSort(a, p, q-1);

QuickSort(a, q+1, r);

}

}

*/

void QuickSort(int a[],int p,const int r)

{

//快速排序算法-主程序

//“尾递归实现方法”是对上面的快速排序主程序实现的一种优化

//系数较小,常用大数组

int q;

while(p r)

{

q = QuickPartition(a, p, r);

QuickSort(a, p, q-1);

p = q + 1;

}

}

/************************希尔排序**********************/

void ShellInsert(int a[],const int p,const int r, int dk)

{

//希尔排序算法的关键子程序-插入排序子程序

int i, j, temp;

for(i=p+dk; i=r; i++)

{

if(a[i] a[i-dk])

{

temp = a[i];

for(j=i-dk; ((j=0) (temp a[j])); j -= dk)

{

a[j+dk] = a[j];

}

a[j+dk] = temp;

}

}

}

void ShellSort(int a[],const int p,const int r,const int dlta[],const int t)

{

//希尔排序算法-主程序

//按增量序列dlta[]中的前t个增量,实现对数组a[]中a[p]到a[r]的排序

//dlta[]可能取值如:1,2,3,5,9 dala[k]=2^(t-k+1)-1 其中0=k=t=ld(b-1)

//增量序列的最后一个值必须是1

//增量序列中的值没有除1以外的因子, 其精确时间复杂度:数学上尚未解决的难题

int k;

for(k=0; kt; k++)

{

ShellInsert(a,p,r,dlta[k]);

}

}

/************************堆排序***********************/

//堆排序,不如快速排序

//但是可用其来实现“优先级队列”

int Parent(int i)

{

return ((i+1)/2-1);

}

int Right(int i)

{

return (2*(i+1)-1);

}

int Left(int i)

{

return (2*(i+1));

}

void Max_Heapify(int a[],const int hplast,const int i)

{

int l, r,largest,temp;

l = Left(i);

r = Right(i);

largest = ((l=hplast) (a[l]a[i])) ? l:i;

if((r=hplast) (a[r]a[largest]))

{

largest = r;

}

if(largest != i)

{

temp = a[i];

a[i] = a[largest];

a[largest] = temp;

Max_Heapify(a,hplast,largest);

}

}

void Build_Max_Heap(int a[],const int p, const int r)

{

int i;

for(i = (p+r)/2; i=p; i--)

{

Max_Heapify(a,r,i);

}

}

void HeapSort(int a[],const int p, int r)

{

int i,temp;

Build_Max_Heap(a,p,r);

for(i = r; i p; i--)

{

temp = a[p];

a[p] = a[i];

a[i] = temp;

r -= 1;

Max_Heapify(a,r,0);

}

}


网站名称:堆排序算法vb.net 堆排序算法流程图
当前URL:http://scyanting.com/article/dooecpi.html