您的位置:首页 > 理论基础 > 数据结构算法

夕拾-数据结构-选择&堆排序

2015-10-10 22:12 281 查看
1.选择排序

记得以前吾最爱的就是选择排序,因为它最容易理解:从当前元素的后面选择一个最小的元素与之交换

void SelectionSort(int a[],int n)
{
	int i,j,min; //min记录比当前元素小的下标 
	for(i=0;i<n-1;i++)
	{	
		min=i; 
		for(j=i+1;j<n;j++)
		{
			if(a[min]>a[j]) min=j; //从当前元素后面的序列后选择一个最小的元素 
		}
		if(min!=i) Swap(a[i],a[min]);   //找到了->交互 
	}
}


2.堆排序

堆排序是快速排序的改进,就如同快速之如冒泡。因为涉及单支变量i*=2,因此i的下标只能从1开始,而堆排序可分2步走:

建立大堆

从最后的分支节点(length/2)开始,让它与孩子节点比较,找到一个大的则与之交换。如此直至顶点即可得到大顶堆。

void HeapSort(int a[],int n)
{
	//从最后的分支节点(length/2)开始,让它与孩子节点比较,
	//找到一个大的则与之交换,如此直至顶点 
	for(int i=n/2;i>0;i--)
	{
		AdjustDownFill(a,i,n); 
	}
	//调整堆 
	for(int i=n;i>1;i--)
	{
		Swap(a[i],a[1]);
		AdjustDownFill(a,1,i-1); 
	} 
}


调整堆

此时顶点是最大的节点,让其与末端节点交换。末端节点成最大节点,软删除末端节点。从顶点向下继续调整,得到新的大顶堆。如此重复,直至剩下1个节点即可

下面是基于交换的思想

void AdjustDownSwap(int a[],int k,int n)
{
	for(int i=k*2;i<=n;i*=2) //左单支下遍历 
	{
		if(i<n && a[i]<a[i+1]) i++; //左孩子存在,且较大 
		if(a[i]<=a[k]) break; //父节点较大,无需交换 
		Swap(a[k],a[i]);  //孩子节点较大 
	}
}


和快速排序一样,交换的思想可以改进为填位的思维:

void AdjustDownFill(int a[],int k,int n)
{
	a[0]=a[k];
	for(int i=k*2;i<=n;i*=2) //左单支下遍历 
	{
		if(i<n && a[i]<a[i+1]) i++; //左孩子存在,且较大 
		if(a[i]<=a[0]) break; //父节点较大,无需交换 
		a[k]=a[i]; //子节点覆盖父节点 
		k=i; //子节点设置待被覆盖节点 
	}
	a[k]=a[0]; // 最后只把a[0]插入适当的位置即可 
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: