排序2—交换排序

本文深入解析冒泡排序与快速排序两大交换排序算法。冒泡排序通过反复比较相邻元素并交换,实现简单但效率较低;快速排序则采用分而治之策略,通过选择枢轴进行分区,实现高效排序。文章附带详细算法描述及代码示例。

前言:

     我们还是老规矩,先看看交换排序的基本思想:两两比较待排序记录的关键字,一旦发现两个记录不满足此需要求时则进行交换,知道整个序列全部满足要求为止。是不是一想到这个就想起来最简单最先接触的冒泡排序呢?

一、冒泡排序

     冒泡排序是一种最简单的交换排序方法,它通过两两比较相邻记录的关键字,如果发生逆序,则进行交换,从而使关键字小的记录如气泡一般逐渐往上“漂浮”,或者“坠落”(这个理解就是从后往前,和从前往后比较的区别)。
     但是机智的你又会发现,很多时候如果我的序列基本有序或者就是有序的,我的冒泡算法还是会依次的进行查找操作,虽然没有进行移动,但是也浪费了时间。所以这里我给出的算法就设置了标志flag,当我没有发生移动时,那么就说明已经有序了,不需要在进行循环操作了。
【算法描述】

void BubbleSort(SqList &L)
{
	//对顺序表L做冒泡排序
	int m,j,flag;
	ElemType t;
    m=L.length-1; flag=1; 				//flag用来标记某一趟排序是否发生交换
    while((m>0)&&(flag==1))
	{
		flag=0;           				//flag置为0,如果本趟排序没有发生交换,则不会执行下一趟排序
        for(j=1;j<=m;j++)
			if(L.r[j].key>L.r[j+1].key) 
			{
				flag=1;					//flag置为1,表示本趟排序发生了交换
				t=L.r[j];L.r[j]=L.r[j+1];L.r[j+1]=t;	//交换前后两个记录
			}							//if
		--m;
    }									//while
}				


二、快速排序(这个可厉害了,同数量级中平均复杂度是最好的)

     机智的你还发现了,冒泡排序稳定,简单,但是我们还是要追求速度,如果我们可以一次就可以消除多个逆序,是不是更快了呢?
     我把这个快速排序称之为“欢快的跳跃”,因为我是从两头逼近式的查找。
【算法描述】
     自己归纳一下就是首先确定枢轴,然后我们想要得到的就是,枢轴的左边比枢轴小,右边比枢轴大。从前往后,找到了交换位置,一直重复。最后就可以得到有序序列了。(哈哈,至于这个具体的概念,大家可以查找)。但是在看概念的时候,就记住,以枢轴为中心,不满足前面比我小,后面比我大就交换位置,从后往前找,交换了在从前往后找,依次操作。计算时间的复杂度相对于冒泡优化了很多。
你看这个图,就这样演示操作的:
在这里插入图片描述
从前往后,从后往前,最后就得到了有序序列。
程序演示会让你清晰很多哦


快速排序的程序演示:

//快速排序
#include <iostream>
using namespace std;
#define  MAXSIZE  20          			//顺序表的最大长度
typedef struct
{
	int key;
	char *otherinfo;
}ElemType;
//顺序表的存储结构                         
typedef struct
{
    ElemType *r;	         						//存储空间的基地址
    int  length;            						//顺序表长度
}SqList;											//顺序表类型
int Partition(SqList &L,int low,int high)
{ 
	//对顺序表L中的子表r[low..high]进行一趟排序,返回枢轴位置
	int pivotkey;
	L.r[0]=L.r[low];                    	//用子表的第一个记录做枢轴记录
	pivotkey=L.r[low].key;		   			//枢轴记录关键字保存在pivotkey中
	while(low<high)
	{										//从表的两端交替地向中间扫描
		while(low<high&&L.r[high].key>=pivotkey) --high;
		L.r[low]=L.r[high];					//将比枢轴记录小的记录移到低端
		while(low<high&&L.r[low].key<=pivotkey) ++low;
		L.r[high]=L.r[low];					//将比枢轴记录大的记录移到高端
	}//while
	L.r[low]=L.r[0];						//枢轴记录到位
	return  low;							//返回枢轴位置
}//Partition
void QSort(SqList &L,int low,int high)
{	//调用前置初值:low=1; high=L.length;
    //对顺序表L中的子序列L.r[low..high]做快速排序
	int pivotloc;
    if(low<high)
	{										//长度大于1
       pivotloc=Partition(L,low,high); 		//将L.r[low..high]一分为二,pivotloc是枢轴位置
       QSort(L,low,pivotloc-1);				//对左子表递归排序
       QSort(L,pivotloc+1,high);        	//对右子表递归排序
	}
}											//QSort
void QuickSort(SqList &L)
{
   //对顺序表L做快速排序
   QSort(L,1,L.length);
}											//QuickSort								
void Create_Sq(SqList &L)
{
	int i,n;
	cout<<"请输入数据个数,不超过"<<MAXSIZE<<"个。"<<endl;
	cin>>n;											//输入个数
	cout<<"请输入待排序的数据:\n";
	while(n>MAXSIZE)
	{
		cout<<"个数超过上限,不能超过"<<MAXSIZE<<",请重新输入"<<endl;
		cin>>n;
	}
	for(i=1;i<=n;i++)
	{
		cin>>L.r[i].key;
		L.length++;
	}
}
void show(SqList L)
{
	int i;
	for(i=1;i<=L.length;i++)
		cout<<L.r[i].key<<endl;
}
void main()
{
	SqList L;
	L.r=new ElemType[MAXSIZE+1];
	L.length=0;
	Create_Sq(L);
	QuickSort(L);
	cout<<"排序后的结果为:"<<endl;
	show(L);
}


后记:

     那么交换排序就结束啦,之后预告选择排序。如有误,评论指出哦,谢谢。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

threecat.up

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值