C++ 交换排序(冒泡排序、快速排序)

交换排序

冒泡排序
思路:
  • 两两比较相邻记录的关键字,若发生逆序,则进行交换。若是从小到大排序,则每轮都选出一个最大的数交换至最右边。
实现:
//冒泡排序
void BubbleSort(SqList &L)
{
	int m = L.length - 1; //一般r[0]闲置用作哨兵单元,所以有L.length-1个
	bool flag = 1; //标记某一趟排序是否发生排序,flag初始化为1进入循环
	while (flag && (m >= 0))
	{
		flag = 0;//若本趟未发生交换,则不会进入下一趟排序
		for (int i = 1; i <= m; i++) //循环遍历,比较所有相邻的两个数的大小,看本趟是否需要交换
			if (L.r[i].key > L.r[i + 1].key)
			{
				flag = 1;//进入if语句说明至少需要交换一次,则标记交换过位置
				//交换位置
				ReadType temp = L.r[i];
				L.r[i] = L.r[i + 1];
				L.r[i + 1]= temp;
			}
		m--;   //执行一次长度减一
	}
}
复杂度
  • 空间复杂度:n2/4~3n2/4
  • 时间复杂度:O(n2)
特点:
  • 稳定排序
  • 移动次数较多,需要排序的数量n较多时不宜采用
  • 可用于链式存储
快速排序
思路:
  1. 如3,9,7,4,6五个数字排序
  2. 随便选一个 其中的数字,比如4,然后把3放到4的左边,把9,7,6放到4的右边。
  3. 然后在9,7,6中选一个数字如7,把6放到7的左边,把9放到7的右边。

总之,在一组数中选一个数,比这个数大放左边,比这个数小的放右边。分成两组,再在每一组中递归的调用这种方法。直到分不下去为止。

实现
//快速排序

//一次排序,以最后一位数的大小作为标准将数列分为两组
int partition(SqList &L ,int low, int high )
{
	L.r[0] = L.r[low];//随便取一个记录放在哨兵中,在这里取最低位的(如果取最高位的数时,则后面的while之后的语句要覆盖高位,而不是低位)
	int pivotkey = L.r[low].key;//把这个记录的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];//若高位的数大于之前记录的数,则覆盖上次覆盖低位的high(上次覆盖低位的high已经保存在低位中),然后如果low<high则,从被覆盖的高位开始while循环
	}
	L.r[low] = L.r[0];//最后将哨兵中的数据归还,因此,左边的都是比该记录小的,右边的都是比该记录大的,到此一次排列结束
	return low; //返回该记录的位置,枢轴位置
}

//递归调用
void quicksort(SqList &L, int low, int high)
{
	if (low < high)
	{
		int pivotloc = partition(L,low,high);//将返回的枢轴位置记录下来,以此为临界点分为左半部分和右半部分两组
		partition(L,low, pivotloc-1);//递归调用左半部分
		partition(L, pivotloc+1,high);//递归调用右半部分
	}
}

void quickSort(SqList &L)
{
	quicksort(L, 1, L.length);
}
复杂度
  • 空间复杂度:O( l o g n log{n} logn)~O(n)
  • 时间复杂度:O(n l o g n log{n} logn)
特点
  • 不是很稳定
  • 较适用于顺序结构
  • 适合于需要排序的数量n较多时,是所有内部排序方法中速度最快的一种。
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值