排序算法——交换排序(冒泡,快速排序)

冒泡排序

思想:

冒泡排序会重复遍历序列,遍历次数每次都减少1次,一次比较两个元素,前数比后数大就交换两数,每轮次比较都会把当前轮次的最大数沉底。

public static int[] bubbleSort(int[] arr){
	for(int i = 0; i < arr.length - 1; i++){ //这里-1是因为第一个元素不与自己比较
		for(int j = 0; j < arr.length - 1 - i; j++){  //这里-1是为了防止数组越界,-i表示比较次数逐次递减
			if(arr[j] > arr[j+1])        //如果前数比后数大,就交换
				swap(arr,j,j+1);
		}
	}
	return arr;
}

复杂度分析:

如果已经有序,则算法只扫描一遍序列,不交换,复杂度为O(n);若无序,则除了遍历一遍,还要所有元素两两交换一次,复杂度为O(n^2
);平均复杂度为O(n^2)。

稳定性:

该排序算法不改变相同元素的相对位置,所以是稳定的。


可以对冒泡排序进行优化,加一个标志位

public static int[] bubbleSort(int[] arr){
	for(int i = 0; i < arr.length - 1; i++){ //这里-1是因为第一个元素不与自己比较
		boolean flag = true;
		for(int j = 0; j < arr.length - 1 - i; j++){  //这里-1是为了防止数组越界,-i表示比较次数逐次递减
			if(arr[j] > arr[j+1]){        //如果前数比后数大,就交换
				swap(arr,j,j+1);
				flag = false;
			}
		}
		//如果flag为真则跳出外层for,flag为真的情况是内层if未执行,说明当前某趟已将序列排成有序,那就不用再做没用的剩下的外层遍历了
		if(flag)
			break;
	}
	return arr;
}

鸡尾酒排序(也叫双端冒泡),第一个for循环从前往后将最大数沉到后面,第二个从后往前将最小数浮到前面

public static int[] bubbleSort(int[] arr){
	for(int i = 0; i < arr.length / 2; i++) {
			for(int j = 0; j < arr.length - 1 - i; j++) {
				if(arr[j] > arr[j+1])
					swap(arr,j,j+1);
			}
			for(int j = arr.length-1; j > i; j--) {
				if(arr[j] < arr[j-1])
					swap(arr,j,j-1);
			}
		}
	return arr;
}

快速排序

思想:

以分治的思想对pivot两端的序列进行排序,每次排序都将比当前pivot小的元素放在pivot左边,大的放pivot右边

public static int[] quickSort(int[] arr, int low, int high){
	if(low < high){
		int pivot = partition(arr,low,high);
		quickSort(arr,low,pivot-1);
		quickSort(arr,pivot+1,high);
	}
	return arr;
}
public static int partition(int[] arr, int low, int high){
	int pivot = arr[low]; //以第一个数作为第一轮的pivot,其实这么做不好,若序列刚好逆序,会导致0(n^2)的复杂度
	while(low < high){
		while(low < high && arr[high] >= pivot)
			high--;
		arr[low] = arr[high]; //比pivot小的元素就放左边
		while(low < high && arr[low] <= pivot)
			low++;
		arr[high] = arr[low]; //比pivot大的元素就放右边
	}
	arr[low] = pivot; //pivot归位
	return low;
	//这两句写成   arr[high] = pivot; return high; 也行,因为跳出 while 循环时 low == high
}

复杂度分析:

如果序列已经有序(正序或逆序),复杂度为O(n^2) ; 平均和最好复杂度为O(nlogn)。

稳定性:

该排序算法改变相同元素的相对位置,所以是不稳定的。

优化:

对于一个基本有序的序列,若取最开始或最后面的数作为pivot,则复杂度升高到跟冒泡排序一样。我们可以有两种取pivot的策略进行优化:

  • 取序列中的随机一个数作为pivot
  • 三位取中:取最左边,最右边,中间这三个数的值位于中间的数作为pivot

还可以采用双轴快排,用两个pivot将序列划分为三个部分分别快排,Java里Arrays.sort方法采取的就是双轴快排

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值