交换排序

1. 冒泡排序

算法思想:不停地比较相邻的记录,如果不满足排序要求,就交换相邻记录,直到所有记录都已经排好序

检查每次冒泡过程中是否已经发生过交换,如果没有,则表明整个数组已经排好序了,排序结束。

/*冒泡排序*/
template <class Record>
void BubbleSort(Record Array[], int n){
	bool NoSwap;         //是否发生了交换的标志
	int i, j;
	for (i = 0; i < n; i++){
		NoSwap = true;    //标志初始为真
		for (j = n - 1; j > i;j--)
			if (Array[j] < Array[j - 1]){   //判断是否逆置
				swap(Array, j, j - 1);    //交换逆置对
				NoSwap = false;          //发生了交换,标志变为假
			}
		if (NoSwap)                   //没有发生交换,则已完成排好排序
			return;
	}
}

算法分析:

  • 稳定
  • 空间代价:O(1)
  • 时间代价分析:比较次数:最少O(n)、最多:n(n-1)/2=O(n^2)
  • 时间代价结论:最大,平均时间代价均为O(n^2)、最小时间代价为O(n),最佳情况下只运行第一轮循环。

2. 快速排序

算法思想:

  • 选择轴值
  • 将序列划分为两个子序列L和R,使得L中所有记录都小于或等于轴值,R中记录都大于轴值。
  • 对于序列L和R递归进行快速排序

分治策略的基本思想:

分治策略的实例:

  • BST查找、插入、删除算法
  • 快速排序、归并排序
  • 二分检索

主要思想:

  • 划分
  • 求解子问题
  • 综合解

轴值选择:

  • 尽可能使L,R长度相等
  • 选择策略:(1)选择最左边记录(2)随机选择(3)选择平均值

一次分割过程:

               

  • 选择轴值并存储轴值
  • 最后一个元素放到轴值位置
  • 初始化下标i,j,分别指向头尾
  • i递增直到遇到比轴值大的元素,并将元素覆盖到j的位置;j递减直到遇到比轴值小的元素,将此元素覆盖到i的位置。
  • 重复上一步直到i==j,将轴值放到i的位置。
/*快速排序算法*/
template <class Record>
void QuickSort(Record Array[], int left, int right){
	//Array[]为待排序数组,left,right分别为数组两端
	if (right <= left)    //只有0或1个记录,就不需排序
		return;
	int pivot = SelectPivot(left, right);    //选择轴值
	swap(Array, pivot, right);             //轴值放在数组末端
	pivot = Partition(Array, left, right);  //分割后轴值正确
	QuickSort(Array, left, pivot - 1);      //左子序列递归快排
	QuickSort(Array, pivot + 1, right);     //右子序列递归快排
}
int SelectPivot(int left, int right){
	//选择轴值,参数left,right分别表示序列的左右段端下标
	return (left + right) / 2;
}
template <class Record>
int Partition(Record Array[], int left, int right){
	//分割函数,分割后轴值已到达正确位置
	int l = left;        //l为左指针
	int r = right;       //r为右指针
	Record TempRecord = Array[r];  //保存轴值
	while (l != r){   //l和r不断向中间移动,直到相遇
		//l指针向右移动,直到找到一个大于轴值的记录
		while (Array[l] <= TempRecord&&r > l)
			l++;
		if (l < r){     //未相遇,将逆置元素换到右边空位
			Array[r] = Array[l];
			r--;    //r指针向左移动一步
		}
		//r指针向左移动,直到找到一个小于轴值的记录
		while (Array[r] >= TempRecord&&r>l)
			r--;
		if (l < r){         //未相遇,将逆置元素换到左空位
			Array[l] = Array[r];
			l++;            //l指针向右移动一步
		}
	} //end while
	Array[l] = TempRecord;//把轴值回填到分界位置l上
	return l;      //返回分界位置l
}

时间代价:

  • 长度为n的序列,时间为T(n)   T(0)=T(1=1
  • 选择轴值时间为常数
  • 分割时间为cn
  • 分割后长度分别为i和n-i-1
  • 左右子序列T(i)和T(n-i-1)
  • 总的时间代价:O(n)

算法分析:

  • 最差情况:时间代价:O(n^2)、空间代价:O(n)
  • 最佳情况:时间代价:O(nlogn)、空间代价:O(log n)
  • 平均代价:时间代价:O(n log n)、空间代价:O(log n)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值