交换类排序 -----------冒泡排序 / 选择排序 / 快速排序

本文深入讲解了三种排序算法:冒泡排序、简单选择排序和快速排序。详细分析了每种算法的思想、代码实现及复杂度,包括时间复杂度和查询次数,帮助读者理解排序算法的原理和优化方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


冒泡排序

思想:两两交换比较相邻的关键字,如果反序则交换,直到没有反序的记录为止。

//顺序表为L
void BubbleSort(sqlist *L){
	int flag = TRUE;
	for(int i=1; i<l->length && flag; ++i){
		flag = FALSE:
		for(int j= l->length; j>=i; j--){
			if(l->r[j] > r[j+1]){
				swap(l,j,j+1);
					flag = TRUE;
			}
		}
	}
}

复杂度分析:时间复杂度

  • 最好比较n-1次
  • 最坏逆序比较 n(n-1)/2

简单选择排序

思想:通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换

代码实现

void SelectSort(sqlist *L){
	int min;  //记录位置
	for(int i=1; i<L->length; ++i){
		min = i;
		for(int j=i+1; j<=L->length; ++j){
			if(l->r[min] > L->[j]){
				min = j;
			}
		if(i != min)
			swap(L,i,min);
		}
	}
}

查询次数:n(n-1)/2
时间复杂度: O( n 2 n^{2} n2)


快速排序

思想:通过一趟排序将待排序记录分割成独立的两部分,其中一部分的关键字均比另一部分记录的关键字小,则可分别对这两部分记录进行排序,以达到整个序列有序的目的。

代码实现

void QSort(Sqlist *L, int low, int hight){
	int pivot;
	if(low < high){
		pivot = Partition(L,low,high); //将序列一分为二,并排序
		QSort(L,low,pivot-1); //对低子序列递归排序
		QSort(L,pivot+1.high);//对高字表递归排序
	}
}

int partition(Sqlist *L,int low, int high){
	int pivotkey;
	pivotkey = L->r[low]; //用字表的第一个记录作为枢纽记录
	while(low < high){    //从表的两端交替想中间扫描
		while(low<high && L->r[high]>=pivotkey)
			high--;
		swap(L,low,high); //将比枢纽记录小的交换到低位
		while(low<high && L->r[low]<=pivotkey)
			low++;
		swap(L,low,high); //将比枢纽记录大的记录交换到高位
	}
	return low; //返回枢纽所在位置
}

-优化中间枢纽(pivotkey)的选取:如果枢纽选取太大或者太小都会影响排序的性能。一般是三数取中 取三个关键字先进行排序,将中间数作为枢纽。

int pivotkey;
int m = low+(high-low);
if(L->r[low] > L->r[high])
	swap(L,low,high);
if(L->r[m] > L->r[high])
	swap(L,low,high);
if(L->r[m] > L->r[low])
	swap(L,low,high);
prvotkey = L->r[low];

对于大的数组说,可以采用九数取中,分别取三组三个数的组,每组取中,然后再从这三个数中取中作为枢纽pivotkey,

-优化递归操作:递归对于性能有一定的影响,QSort函数在其尾部有两次递归操作,如果带我排序的序列划分极端不平衡,递归深度将趋近于n,而不是平衡时的 log ⁡ 2 n \log_2{n} log2n,这样不仅仅是速度慢的问题了。栈的大小是很有限的,每次递归调用都会耗费一定栈的空间,函数的参数越多,每次递归消耗的空间也越多。因此如果能减少递归,将会很大程度的提高性能。

改进代码

void QSort(Sqlist *L,int low, int high){
	int pivot;
	if((high-low) > MAX_LENGTH_INSERT_SORT){
		while(low < high){
			pivot = Parrtition(L,low,high);
			QSort(L,low,pivot-1);
			low = pivot+1;
		}
	}
	else 
		Insertsort(L);
}

把if该成while后,第一次递归以后,变量low在下面用不到,可以将pivot+1赋值给low,再循环一次后,来一次Partition(L,low,high),其效果等同于QSort(L,pivot+1,high),结果相同,但因采用迭代而不是递归的方法可以缩减堆栈深度,从而提高了整体性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值