排序——交换排序(冒泡排序、快速排序)

这是排序部分的第二篇文章,其他的排序方法可以点击下面的传送门(•͈ᴗ•͈ૢૢ)❊⿻*

排序算法合辑

  1. 排序——插入排序(直接插入排序、希尔排序、折半插入排序)
  2. 排序——交换排序(冒泡排序、快速排序)
  3. 排序——选择排序(简单选择排序、堆排序)

冒泡排序(bubble sort)

冒泡排序又称起泡排序,基本思想是两两比较相邻记录的关键码,如果反序则交换。

排序过程

  1. 将整个待排序的记录序列划分成有序区和无序区,初始时有序区为空,无序区包括所有待排序的记录。
  2. 对无序区从前向后依次将相邻记录的关键码进行比较,若反序则交换,从而使得
    关键码小的记录向前移,关键码大的记录向后移(像水中的气泡,体积大的先浮上来)
  3. 重复执行2直到无序区中没有反序的记录。

在这里插入图片描述

例如: 待排序序列453,143,49,6,31,1,28
在这里插入图片描述
……以此类推,直到整个序列排序完成。例子里可以看出来每次交换都有一个数到达它的最终位置(之后排序这个数字的位置都不会变了嗷₍₍ (ง ˙ω˙)ว ⁾⁾)。

代码

void BubbleSort(int a[],int n)
{
	for(int i=0;i<n-1;i++)
	{  
		/*设置一个标志,如果依次循环中不再出现交换,
		证明每个记录都到达了它的最终位置上,
		即可跳出循环停止排序过程。*/
		bool flag=false;  
		for (int j=0;j<n-i-1;j++)
		{
			if (a[j]>a[j+1])
			{
				int mid=a[j];
				a[j]=a[j+1];
				a[j+1]=mid;
				flag=true;
			}
		}
		if(flag==false) return;
	}
}

算法分析

/时间复杂度空间复杂度
最好情况 O ( n ) O(n) O(n)
最坏情况 O ( n 2 ) O(n^2) O(n2)
平均 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1 ) O(1)

实例

待排序序列453,143,49,6,31,1,28

#include <iostream>
using namespace std;
void Print(int a[],int n)
{
	for (int i=0;i<n;i++)
	{
		cout<<a[i]<<" ";
	}
	cout<<endl;
}
void BubbleSort(int a[],int n)
{
	for(int i=0;i<n-1;i++)
	{
		bool flag=false;
		for (int j=0;j<n-i-1;j++)
		{
			if (a[j]>a[j+1])
			{
				int mid=a[j];
				a[j]=a[j+1];
				a[j+1]=mid;
				flag=true;
			}
		}
		if(flag==false) return;
		/*-------排序过程------*/
		cout<<"第"<<i+1<<"趟排序:"; 
		Print(a,n); 
		/*-------排序过程------*/
	}
}
int main()
{
	int b[7]={453,143,49,6,31,1,28};
	cout<<"待排序数组:"<<endl;
	Print(b,7);
	BubbleSort(b,7);
	cout<<"排序结果:"<<endl;
	Print(b,7);
	return 0;
}

快速排序(quick sort)

排序过程

快速排序是对起泡排序的一种改进,基本思想是首先选一个轴值(pivot即比较的基准)将待排序记录划分成独立的两部分,左侧记录的关键码均小于或等于轴值,右侧记录的关键码均大于或等于轴值,然后分别对这两部分重复上述过程,直到整个序列有序。
在这里插入图片描述
举个栗子: 待排序序列:23,12,49,6,31,19,28
在这里插入图片描述
以第一行数据为例:
在这里插入图片描述
例子中可以看出,每次交换轴值都会到达它的最终位置(之后排序这个数字的位置都不会变了嗷₍₍ (ง ˙ω˙)ว ⁾⁾)。

代码

我参考了两本书,列了两个写法。两个写法的区别就在于int partition(int a[],int low,int high)这个函数不太一样。
写法一
不借助pivot做暂存空间。每次比较发现逆序之后直接进行交换。

void change(int &a, int &b)					//自定义的交换函数
{
	int mid=a;
	a=b;
	b=mid;
}
int partition(int a[],int low,int high)
{
	while(low<high)
	{
		while(low<high && a[low]<=a[high])
			high--;
		change(a[low],a[high]);
		while(low<high && a[low]<=a[high])
			low++;
		change(a[low],a[high]);
	}
	return low; 							//return high也行 
}
void QuickSort(int a[],int low,int high)
{
	if(low<high)
	{
		int p=partition(a,low,high);
		QuickSort(a,low,p-1);
		QuickSort(a,p+1,high);
	}
}

写法二
借助pivot做暂存空间。最后再将轴值放入。

int partition(int a[],int low,int high)
{
	int pivot = a[low];
	while(low<high)
	{
		while(low<high && a[high]>=pivot)
			high--;
		a[low]=a[high];
		while(low<high && a[low]<=pivot)
			low++;
		a[high]=a[low];
	}
	a[low]=pivot;
	return low; 						//return high也行 
}
void QuickSort(int a[],int low,int high)
{
	if(low<high)
	{
		int p=partition(a,low,high);	//第一次划分
		QuickSort(a,low,p-1);  			//递归对左侧划分
		QuickSort(a,p+1,high);			//递归对左侧划分
	}
}

算法分析

/时间复杂度空间复杂度
最好情况 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) O ( l o g 2 n ) O(log_2n) O(log2n)
最坏情况 O ( n 2 ) O(n^2) O(n2) O ( n ) O(n) O(n)
平均 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n) O ( l o g 2 n ) O(log_2n) O(log2n)

实例

在这里插入图片描述

/*---------------------写法一-----------------------*/
#include <iostream>
using namespace std;
void Print(int a[],int n)
{
	for (int i=0;i<n;i++)
	{
		cout<<a[i]<<" ";
	}
	cout<<endl;
}
void change(int &a, int &b)
{
	int mid=a;
	a=b;
	b=mid;
}
int partition(int a[],int low,int high)
{
	while(low<high)
	{
		while(low<high && a[low]<=a[high])
			high--;
		//if(low<high)
		{
			change(a[low],a[high]);
		//	low++;
		}
		while(low<high && a[low]<=a[high])
			low++;
		//if(low<high)
		{
			change(a[low],a[high]);
		//	high--;
		}
	}
	Print(a,7);  //过程输出 
	return low; //return high也行 
}
void QuickSort(int a[],int low,int high)
{
	if(low<high)
	{
		int p=partition(a,low,high);
		QuickSort(a,low,p-1);
		QuickSort(a,p+1,high);
	}
}
int main()
{
	int a[7]={23,12,49,6,31,19,28};
	
	cout<<"待排序序列:"<<endl;
	Print(a,7);
	cout<<endl<<"划分过程"<<endl; 
	QuickSort(a,0,6);
	cout<<endl<<"排序结果:"<<endl;
	Print(a,7);

	return 0;
}
/*---------------------写法二-----------------------*/
#include <iostream>
using namespace std;
void Print(int a[],int n)
{
	for (int i=0;i<n;i++)
	{
		cout<<a[i]<<" ";
	}
	cout<<endl;
}
int partition(int a[],int low,int high)
{
	int pivot = a[low];
	while(low<high)
	{
		while(low<high && a[high]>=pivot)
			high--;
		a[low]=a[high];
		while(low<high && a[low]<=pivot)
			low++;
		a[high]=a[low];
	}
	a[low]=pivot;
	Print(a,7); //过程输出 
	return low; //return high也行,可以自己试一下,因为这时候low=high为pivot的最终位置
}
void QuickSort(int a[],int low,int high)
{
	if(low<high)
	{
		int p=partition(a,low,high);
		QuickSort(a,low,p-1);
		QuickSort(a,p+1,high);
	}
}
int main()
{
	int a[7]={23,12,49,6,31,19,28};
	
	cout<<"待排序序列:"<<endl;
	Print(a,7);
	cout<<endl<<"划分过程"<<endl; 
	QuickSort(a,0,6);
	cout<<endl<<"排序结果:"<<endl;
	Print(a,7);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ann's Blog

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

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

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

打赏作者

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

抵扣说明:

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

余额充值