交换排序(冒泡排序和快速排序)

所谓交换,就是根据序列中的两个元素关键字的比较结果来对换这两个记录在序列中的位置,主要的有冒泡和快速排序

一、冒泡排序

       冒泡基本思想:假设待排序表长为n,从后往前(从前往后)两两比较相邻的元素的值,若为逆序,则交换他们,直到序列比较完,则称为一趟冒泡:结果将最小的元素交换到待排序列的第一个位置。下一趟冒泡时,前一趟确定的最小元素不再参与比较。这样最多做 n-1 趟冒泡就能把所有的元素排好序。

       

public class BubbleSort {

	public void bubbleSort(int[] array) {
		int length = array.length;
		boolean flag = false; // 标志元素是否进行了交换
		for (int i = 0; i < length-1; i++) {
			flag = false;
			for (int j = length-1; j > i; j--) {
				if(array[j-1] > array[j]) {
					swap(array, j); // 交换两元素顺序
					flag = true;
				}
			}
			// 如果没有进行过交换,则表示数组有序
			if(flag == false) {
				break;
			}
		}
		System.out.println(Arrays.toString(array));
	}


	private void swap(int[] array, int j) {
		int temp = array[j-1];
		array[j-1] = array[j];
		array[j] = temp;
	}

	
	@Test
	public void test() {
		int[] arr = new int[]{1, 2, 3, 8, 6, 7, 9};
		bubbleSort(arr);
	}
	
}

空间效率:仅使用了常数个辅助单元,因而空间复杂度为O(1)

时间效率:当初始序列有序时,比较n-1次,移动0次,最好的情况下时间复杂度是O(n),当初始序列逆序时,最坏的情况下时间复杂度是O(n2),平均时间复杂度为O(n2),稳定的排序方法

二、快速排序

关于快速排序,之前写过一篇比较详细的https://blog.csdn.net/qq_36189382/article/details/78167286,大多面试也会问快排的原理,时间复杂度,这里简单带过

快速排序是对冒泡排序的一种改进。其基本思想是基于分治算法:在待排序表中任取一个元素pivot作为基准,通过一趟排序将待排序表划分为独立的两部分,小于基准的一组,大于或者等于基准的一组,则pivot放在了其最终的位置上,这个过程称为一趟快速排序。然后分别递归的对两个子表进行重复上述操作,直至每部分内只有一个元素或空为止,即所有的元素都放在了其最终位置上。

public class QuickSort {

	public void quickSort(int[] array, int low, int high) {
		if(low < high) { // 跳出递归的条件
			int pivotpos = partition(array, low, high);  // 划分操作,初始以要第一个元素为枢纽元
			quickSort(array, low, pivotpos-1); // 依次对两子表进行递归排序
			quickSort(array, pivotpos+1, high);
		}
	}

	// 把初始序列表划分为满足条件的两个子表
	private int partition(int[] array, int low, int high) {
		int pivot = array[low]; // 枢纽元
		while(low < high) {
			while(low < high && array[high] >= pivot) {
				high--;
			}
			array[low] = array[high];
			while(low < high && array[low] <= pivot) {
				low++;
			}
			array[high] = array[low];
		}
		array[low] = pivot;
		return low;
	}
	
	@Test
	public void test() {
		int[] arr = new int[]{1, 10, 3, 8, 6, 7, 9};
		quickSort(arr, 0, arr.length-1);
		System.out.println(Arrays.toString(arr));
	}
}

快排的关键在于划分操作,同时快排的性能也主要取决于划分操作的好坏
 * 空间效率:快排是递归的,需要借助一个递归工作栈来保存每一层递归调用的必要信息,其容量应该与递归调用的最大深度一致
 * 最好的情况是log2(n+1),最坏的情况因为要进行n-1次递归调用,所以栈的深度为O(n),平均情况下栈的深度为log2(n)
 * 时间效率:快排的运行时间与划分是否对称有关,最坏情况发生在两个区域分别包含n-1个元素和0个元素时,即
 * 对应的初始排序表基本有序或基本逆序,就得到最坏的时间复杂度O(n2)
 * 平均时间复杂度为O(nlog2N),快速排序是所有内部排序算法中平均性能最优的排序算法,不稳定的算法
 * 提高快排的效率可用:三数中值法

点赞