严蔚敏《数据结构》 快速排序&堆排序

快速排序 

        快速排序是对冒泡排序进行改进的一种交换排序,可以大大加快排序的速度。

        快速排序具体的算法思想是在待排序的序列中任选一个数作为枢轴值(pivotkey),用双指针一个指向表的第一个值(low=1),另一个指向最后一个值(high=L.length)。若high指针指向的值大于枢轴值,则high指针向前移动,否则将high与枢轴记录交换。再从low指针的位置找到比枢轴值大的记录放到high的位置。当low=high时将初始选中的枢轴值放在那个位置。这样,在枢轴值两侧分为了两个都大于它或都小于它的两个子表,并按以上步骤不断递归最后得到正确的排序序列。

        算法如下

int Partition(SqList &L,int low,int high)    //对子表进行排序,返回枢轴位置 
{
	L.r[0]=L.r[low]; 
	int pivotkey=L.r[low];    //将关键字记录在pivotkey中 
	while(low<high)
	{
		while(low<high&&L.r[high]>=pivotkey)
		{
			--high;
		}
		L.r[low]=L.r[high];
		while(low<high&&L.r[low]<=pivotkey)
		{
			++low;
		}
		L.r[high]=L.r[low];
	} 
	L.r[low]=L.r[0];
	return low;
}
void QSort(SqList &L,int low,int high)
{
    if(low<high)
    {
    	int pivotloc=Partition(L,low,high);
    	QSort(L,low,pivotloc-1);   //左子表递归 
    	QSort(L,pivotloc+1,high);  //右子表递归 
	}
}
void QuickSort(SqList &L)
{
	QSort(L,1,L.length);
	cout<<"快速排序为: ";
	for(int i=1;i<=L.length;i++)
	{
		cout<<L.r[i]<<" ";
	}
 }

 堆排序

        堆排序是一种树形选择排序,借助完全二叉树的关系利用大根堆或小根堆实现排序的算法。

堆排序的实现分为建初堆和调整堆两个步骤。

        调整堆是对完全二叉树中的某一节点,选出它左右孩子中较大孩子的标号并将它与选中节点进行比较。若该节点小于其左右孩子中较大的节点,则将其位置进行交换。

        建初堆是从最后一个分支节点(n/2)开始,将这个节点到1的所有节点都调整为堆。

        采用以上方法可将待排序的完全二叉树调整为大根堆,堆排序则是将头结点与最后一个节点交换,并重新调整为大根堆,以此不断递归,最后输出升序的序列。

        算法如下:

void HeapAdjust(SqList &L,int s,int m)
 {
 	int rc=L.r[s];
 	for(int j=2*s;j<=m;j*=2)
 	{
 		if(j<m&&L.r[j]<L.r[j+1])    //取较大的左右孩子的标号 
 		{
 			++j;
		}
		 else if(rc>L.r[j])     //将根s与较大的左右孩子比较 
		 {
		 	break;
		 }		
		L.r[s]=L.r[j];
		L.r[j]=rc;
		s=j;
	 }
 }
 void CreateHeap(SqList &L)
 {
 	int n=L.length;
 	for(int i=n/2;i>0;i-=1)
 	{
 		HeapAdjust(L,i,n);
	}
 }
 void HeapSort(SqList &L)
 {
 	CreateHeap(L);
 	int i;
 	for(i=L.length;i>1;i-=1)
 	{
 		int x=L.r[1];
 		L.r[1]=L.r[i];
 		L.r[i]=x; 
		HeapAdjust(L,1,i-1);		//重新调整为大根堆 
    }
    cout<<"堆排序为: ";
	for(i=1;i<=L.length;i++)
	{
		cout<<L.r[i]<<" ";
	}
 }

        快速排序和堆排序都是不稳定的排序算法。

时间复杂度:

        快速排序最好情况为O(nlog2n),最坏情况为O(n方),平均情况为O(nlog2n)

        堆排序最好最坏平均情况都是O(nlog2n)

空间复杂度:

        快速排序为O(log2n),堆排序为O(1)

完整代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
#define MAXSIZE 20
struct SqList
{
	int r[MAXSIZE+1];
	int length;
};
int Partition(SqList &L,int low,int high)    //对子表进行排序,返回枢轴位置 
{
	L.r[0]=L.r[low]; 
	int pivotkey=L.r[low];    //将关键字记录在pivotkey中 
	while(low<high)
	{
		while(low<high&&L.r[high]>=pivotkey)
		{
			--high;
		}
		L.r[low]=L.r[high];
		while(low<high&&L.r[low]<=pivotkey)
		{
			++low;
		}
		L.r[high]=L.r[low];
	} 
	L.r[low]=L.r[0];
	return low;
}
void QSort(SqList &L,int low,int high)
{
    if(low<high)
    {
    	int pivotloc=Partition(L,low,high);
    	QSort(L,low,pivotloc-1);   //左子表递归 
    	QSort(L,pivotloc+1,high);  //右子表递归 
	}
}
void QuickSort(SqList &L)
{
	QSort(L,1,L.length);
	cout<<"快速排序为: ";
	for(int i=1;i<=L.length;i++)
	{
		cout<<L.r[i]<<" ";
	}
 }
 
 //堆排序 
 void HeapAdjust(SqList &L,int s,int m)
 {
 	int rc=L.r[s];
 	for(int j=2*s;j<=m;j*=2)
 	{
 		if(j<m&&L.r[j]<L.r[j+1])    //取较大的左右孩子的标号 
 		{
 			++j;
		}
		 else if(rc>L.r[j])     //将根s与较大的左右孩子比较 
		 {
		 	break;
		 }		
		L.r[s]=L.r[j];
		L.r[j]=rc;
		s=j;
	 }
 }
 void CreateHeap(SqList &L)
 {
 	int n=L.length;
 	for(int i=n/2;i>0;i-=1)
 	{
 		HeapAdjust(L,i,n);
	}
 }
 void HeapSort(SqList &L)
 {
 	CreateHeap(L);
 	int i;
 	for(i=L.length;i>1;i-=1)
 	{
 		int x=L.r[1];
 		L.r[1]=L.r[i];
 		L.r[i]=x; 
		HeapAdjust(L,1,i-1);		//重新调整为大根堆 
    }
    cout<<"堆排序为: ";
	for(i=1;i<=L.length;i++)
	{
		cout<<L.r[i]<<" ";
	}
 }
 
int main()
{
	SqList L;
	//SqList L.r[MAXSIZE];
	cout<<"输入数组长度:"<<endl;
	cin>>L.length;
	cout<<"输入数据:"<<endl;
	for(int i=1;i<=L.length;i++)
	{
		cin>>L.r[i];
	}
	QuickSort(L);
	cout<<endl;
	HeapSort(L); 
}
 

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1.1 数组和字符串 2 1.1.1 一维数组的倒置 2 范例1-1 一维数组的倒置 2 ∷相关函数:fun函数 1.1.2 一维数组应用 3 范例1-2 一维数组应用 3 1.1.3 一维数组的高级应用 5 范例1-3 一维数组的高级应用 5 1.1.4 显示杨辉三角 7 范例1-4 显示杨辉三角 7 ∷相关函数:c函数 8 1.1.5 魔方阵 9 范例1-5 魔方阵 9 1.1.6 三维数组的表示 14 范例1-6 三维数组的表示 14 ∷相关函数:InitArray函数 1.1.7 多项式的数组表示 17 范例1-7 多项式数组的表示 17 1.1.8 查找矩阵的马鞍点 19 范例1-8 查找矩阵的马鞍点 19 ∷相关函数:Get_Saddle函数 1.1.9 对角矩阵建立 21 范例1-9 对角矩阵建立 21 ∷相关函数:Store函数 1.1.10 三对角矩阵的建立 22 范例1-10 三对角矩阵的建立 22 ∷相关函数:Store函数 1.1.11 三角矩阵建立 24 范例1-11 三角矩阵建立 24 ∷相关函数:Store函数 1.1.12 对称矩阵的建立 25 范例1-12 对称矩阵的建立 25 ∷相关函数:store函数 1.1.13 字符串长度的计算 28 范例1-13 字符串长度的计算 28 ∷相关函数:strlen函数 1.1.14 字符串的复制 29 范例1-14 字符串的复制 29 ∷相关函数:strcpy函数 1.1.15 字符串的替换 31 范例1-15 字符串的替换 31 ∷相关函数:strrep函数 1.1.16 字符串的删除 33 范例1-16 字符串的删除 33 ∷相关函数:strdel函数 1.1.17 字符串的比较 35 范例1-17 字符串的比较 35 ∷相关函数:strcmp函数 1.1.18 字符串的抽取 36 范例1-18 字符串的抽取 36 ∷相关函数:substr函数 1.1.19 字符串的分割 38 范例1-19 字符串的分割 38 ∷相关函数:partition函数 1.1.20 字符串的插入 40 范例1-20 字符串的插入 40 ∷相关函数:insert函数 1.1.21 字符串的匹配 42 范例1-21 字符串的匹配 42 ∷相关函数:nfind函数 1.1.22 字符串的合并 43 范例1-22 字符串的合并 43 ∷相关函数:catstr函数 1.1.23 文本编辑 45 范例1-23 文本编辑 45 ∷相关函数:StrAssign函数 1.2 栈和队列 54 1.2.1 用数组仿真堆栈 54 范例1-24 用数组仿真堆栈 54 ∷相关函数:push函数 pop函数 1.2.2 用链表仿真堆栈 57 范例1-25 用链表仿真堆栈 57 ∷相关函数:push函数 pop函数 1.2.3 顺序栈公用 59 范例1-26 顺序栈公用 59 ∷相关函数:push函数 pop函数 1.2.4 进制转换问题 61 范例1-27 进制转换问题 61 ∷相关函数:MultiBaseOutput函数 1.2.5 顺序队列操作 64 范例1-28 顺序队列操作 64 ∷相关函数:push函数 pop函数 1.2.6 循环队列 66 范例1-29 循环队列 66 ∷相关函数:EnQueue函数 DeQueue函数 1.2.7 链队列的入队、出队 69 范例1-30 链队列入队、出队 69 ∷相关函数:push函数 pop函数 1.2.8 舞伴问题 71 范例1-31 舞伴问题 71 ∷相关函数:EnQueue函数 DeQueue函数 DancePartner函数 1.3 链表 75 1.3.1 头插法建立单链表 75 范例1-32 头插法建立单链表 75 ∷相关函数:createlist函数 1.3.2 限制链表长度建立单链表 77 范例1-33 限制链表长度建立长单链表 77 ∷相关函数:createlist函数 1.3.3 尾插法建立单链表 79 范例1-34 尾插法建立单链表 79 ∷相关函数:createlist函数 1.3.4 按序号查找单链表 80 范例1-35 按序号查找单链表 80 ∷相关函数:getnode函数 1.3.5 按值查找单链表 82 范例1-36 按值查找单链表 82 ∷相关函数:locatenode函数 1.3.6 链表的插入 84 范例1-37 链表的插入 84 ∷相关函数:insertnode函数 1.3.7 链表的删除 86 范例1-38 链表的删除 86 ∷相关函数:deletelist函数 1.3.8 归并两个单链表 88 范例1-39 归并两个单链表 88 ∷相关函数:concatenate函数 1.3.9 动态堆栈 90 范例1-40

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值