ソート - ソート・ヒープ

まず、アルゴリズム記述

  • ヒープ:ヒープデータ構造であり、スタックは、十分に満足完全二分木、二分木と見なすことができる。任意の非リーフノードの値がより大きい(またはより小さい)ではない、その左右の子ノードの値。小さなお子様連れの大きな父は、そのようなヒープヒープは、大きなトップと呼ばれる場合は、大きな父場合、子、このような小さなヒープは、トップヒープと呼ばれます。
  • スタック:現在のノードの子ノードの値を比較する(Aとする)、その値は子ノードが存在しているよりも大きい場合には、そして、次の層がに交換から最大値を選択します上記のプロセスは、子ノードの値になるまで繰り返した場合、最大の値よりも小さいです。

アルゴリズムの第2、アイデア

ヒープソート実行処理記述(大トップスタックの例)次のように

  1. 建設スタック:バイナリランダムシーケンスの最初の非リーフノードで始まるは、ヒープの各ノードについて、下から上へ、右から左に、完全に決定されます。
  2. 並べ替え:ヒープの終わりが構築された後、ヒープ要素の上部が最大の要素である、と私たちは、交換される最後の要素となり、キーワードのカオス系列を減らすために、この時点では、添字nの位置を置く最大の要素、キーワードの順序付けられたシーケンスを高めます。我々再びスタックのn-1個の要素の前に、その後スタック要素添字の上部にN-1位。ヒープの残りの要素は、ソートが完了するまで、このプロセスを繰り返します。

第三に、アルゴリズムのプロセス

今完了し6つの整数{6,5、14,7、8,1}大きなトップヒープソート

(1)ビルドヒープ

  1. 調整14、14> 1、スタック、無調整の定義を満たします。
  2. リーフノード5の交換後交換5及び8は、となるように調整5,5 <7,5 <8は、スタックは、定義を満たしていないので、調整が完了する。
  3. 調整6,6 <8,6 <14は、スタックの定義ので、交換機6及び14を満たしません。スタックの定義を満たす、6,6> 1を調整するために続けて、無調整ません
    ここに画像を挿入説明

(2)ソート1

  1. 最後の交換体1と、スタック14の上部には、キーワードの順不同のシーケンス、1つの順序付けられたシーケンスを追加するキーワードを削減します。
  2. 調整1,1 <8,1 <6,1及び8の交換。交換機1に1,1> 5,1> 7,7を調整し続けると、交換がリーフノードになるので、調整された後
    ここに画像を挿入説明

(3)ソート2

ここに画像を挿入説明

(4)ソート3

ここに画像を挿入説明

(5)ソート4

ここに画像を挿入説明

(6)5ソーティング

ここに画像を挿入説明


第四に、ヒープソート挿入、削除

(1)挿入ノード

需要在插入结点后保持堆的性质,因此需要先将要插入的结点x放在最底层的最右边,插入后满足完全二叉树的特点;然后把 x 依次向上调整到合适位置以满足堆的性质。

(2)删除结点

当删除堆的一个结点时,原来的位置就会出现一个空缺,填充这个空缺的方法就是,把最底层最右边的叶子的值赋给该空缺并下调到合适位置,最后把该叶子删除。


五、实现

void translate(int R[],int low,int high)	//	在数组R[low]到R[high]的范围内对在位置low的结点进行调整
{
	int i=low;	//	父结点
	int j=i*2;	//	左孩子
	int temp=R[i];	//	记录父结点
	while(j<=high)
	{
		if(j<high && R[j]<R[j+1])	//	若右孩子比较大,则把j指向右孩子
			j++;
		if(temp<R[j])
		{
			R[i]=R[j];	//	将R[j]调整到父结点的位置
			i=j;	//	修改i和j的值,以便继续向下调整
			j=2*i;
		}
		else
			break;	//	父结点较大,调整结束
	}
	R[i]=temp;	//	将被调整结点的值放入最终位置
}
void heapSort(int R[],int n)
{
	int i;
	int temp;
	for(i=n/2;i>=1;i--)	//	建立初始堆
	{
		translate(R,i,n);
	}
	for(i=n;i>=2;i--)
	{
		temp=R[i];	//	无序序列的堆顶和最后一个元素交换
		R[i]=R[1];
		R[1]=R[i];
		translate(R,1,i-1);
	}
}

六、算法性能分析

(1)时间复杂度分析

对于函数 translate(),显然 j 走了一条从当前结点到叶子结点的路径,完全二叉树的高度为 floor(log(n+1)),即对每一个结点调整的时间复杂度为 O(log n)

对于函数 heapSort(),基本操作总次数应该是两个并列的 for 循环中的基本操作次数之和,第一个循环的基本操作次数为 O(log n)*(n/2),第二个循环的基本操作次数为 O(log n)*(n-1),因此整个算法的基本操作次数为 O(log n)*(n/2) + O(log n)*(n-1),故其平均时间复杂度、最坏时间复杂度、最好时间复杂度均为 O(nlog n)

堆排序和快速排序的最好时间复杂度都是 O(nlog n),那么两者之间有什么不同呢?

  1. 10w 数据量两种排序速度基本相当,但是堆排序交换次数明显多于快速排序;10w+数据,随着数据量的增加快速排序效率要高的多,数据交换次数快速排序相比堆排序少的多。

  2. 实际应用中,堆排序的时间复杂度要比快速排序稳定,快速排序的最差的时间复杂度是O(n^2),平均时间复杂度是O(nlog n)。堆排序的时间复杂度稳定在O(nlog n)。但是从综合性能来看,快速排序性能更好。

(2)空间复杂度分析

空间复杂度为 O(1)

(3)稳定性

我々は、以下の親ノードの子ノードである小さい、請求項2に記載のヒープの最上部2に等しいより大きいスタックの最上部が大親ノードの子ノードを必要とする、私は子供の積層構造は、2Iおよび2I + 1ノードであるノードを知っています。長さn、ヒープソートプロセス及び3の最初のシーケンスにおけるその子ノードの最大値が選択され(大スタックトップ)N / 2又は最小(マイナー頂点スタック)から、これらの三つの要素の選択もちろん、安定性を損なうません。しかし、右から左にスタックを構築するプロセスは、非リーフノードは、n / 2-1、N / 2-2、親ノードがこれらの要素を選択する...、それは意志であるとき、下から上に非リーフノードを選択します不安定化。親ノードの後ろにN / 2の可能なノードの親は、2つの同一の要素の間で同じ、その後安定背後要素を交換しない第一のスイッチング素子が経過交換、及び最初のn / 2-1それが破壊されました。だから、ヒープソートは安定ソートアルゴリズムではありません。

おすすめ

転載: blog.csdn.net/starter_____/article/details/94193977