排序算法-快速排序和堆排序

排序算法-快速排序和堆排序

一:快速排序算法

快速排序在平均状况下,排序 n 个项目要Ο(n log n)次比较。在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见。事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来。

快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists)。

算法步骤:

1 从数列中挑出一个元素,称为 “基准”(pivot),

2 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。

3 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。

在实现过程中,最后才对初始关键字赋值,注意交换过程中赋值下标顺序的正确性。

#include "iostream.h"

void Qsort(int a[],int low,int high)
{
	int pivot,privotloc;
	int first,last;
	if(low>=high)
	{
		return;
	}
	first=low;last=high;
	pivot=a[first];
	while(first<last)
	{
		while(first<last&&a[last]>=pivot)--last;   
		a[first]=a[last]; //比初始关键字小的移到数组前面
		while(first<last&&a[first]<=pivot)++first;
		a[last]=a[first]; //比初始关键字小的移到数组末端
	}
	a[first]=pivot;  //初始关键字将数组分成两部分后,记录位置
	privotloc=first;
	Qsort(a,low,privotloc-1);   //递归实现前半区
	Qsort(a,privotloc+1,high);	//递归实现后半区

}

void main()
{
	int b[8]={49,38,65,97,76,13,27,49};  //实例
	Qsort(b,0,7);
	for(int i = 0; i <8; i++)
    {
        cout <<b[i]<<endl;
    }
}

二:堆排序算法

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

堆排序的平均时间复杂度为Ο(nlogn) 。

算法步骤:

  1. 创建一个堆H[0..n-1]
  2. 把堆首(最大值)和堆尾互换

3. 把堆的尺寸缩小1,并调用shift_down(0),目的是把新的数组顶端数据调整到相应位置

4. 重复步骤2,直到堆的尺寸为1

编写代码时,出现了很多次错误,原因主要是:数组实现时,下标从0开始的,多处地方的下标没注意导致数组越界。

#include "iostream.h"
void heapadjust(int a[],int s,int m)
{
	int temp=a[s];
	for(int j=2*s+1;j<m-1;j=j*2)
	{
		if(j<(m-1)&&a[j]<a[j+1])++j;  //子节点中较大的一个
		if(temp>a[j]) break;   //temp插入到此处
		a[s]=a[j];    //不满足堆定义,交换
		s=j;
	}
	a[s]=temp;    //插入
}

void heapsort(int a[],int len)
{
	int temp;
	for(int i=len/2-1;i>=0;--i)   //建立初始的大顶堆
	{
		heapadjust(a,i,len);
	}
	for(i=len-1;i>0;--i)
	{
		temp=a[0];
		a[0]=a[i];
		a[i]=temp;   //堆顶与未排序的最后一个记录交换

		heapadjust(a,0,i);  //重新调整为大顶堆
	}
}

void main()
{
	int b[8]={49,38,65,97,76,13,27,49};
	heapsort(b,8);
	for(int i = 0; i <8; i++)
    {
        cout <<b[i]<<endl;
    }
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值