May 15, 2018

面试官逼问系列之:四种排序算法

请你使用java语言描述插入排序、选择排序、交换排序

插入排序

                  
	////////////////////////////////////////////	插入排序           ////////////////////////////////////////////
	/** 直接插入排序 **/
	public void zhijiecharupaixu(int[] array) throws Exception {
		
		for(int i = 0; i < array.length-1; i++){
			int temp = array[i+1];
			int j = i;
			for(; j > -1 && temp < array[j]; j--){
				array[j+1] = array[j];	//后移出temp的位置
			}
			array[j+1] = temp;
		}
		System.out.println(Arrays.toString(array));
	} 
	
	/** 希尔排序 **/
	public void xierpaixu(int[] array) throws Exception {
		
		double d1 = array.length;
		while(true){
			d1 = Math.ceil(d1 / 2);
			int d = (int) d1;
			for(int x = 0; x < d; x++){
				for(int i = x; i < array.length-d; i += d){//每次增加d,而不是1
					int temp = array[i+d];
					int j = i;
					for(; j > -1 && temp < array[j]; j -= d){
						array[j+d] = array[j];	//后移出temp的位置
					}
					array[j+d] = temp;
				}
			}
			if(d == 1) break;
		}
		System.out.println(Arrays.toString(array));
	}
                  
                

选择排序

                  
////////////////////////////////////////////	选择排序           ////////////////////////////////////////////
/** 直接选择排序 **/
public void zhijiexuanzepaixu(int[] array) throws Exception {
	for(int i = 0; i < array.length; i++){
		int idx = i;
		int temp = array[i];
		for(int j = i+1; j < array.length; j++){	//选择最小的与i交换
			if(array[j] < temp){
				idx = j;
				temp = array[j];
			}
		}
		array[idx] = array[i];
		array[i] = temp;
	}
	System.out.println(Arrays.toString(array));
}

/**
 * 【堆排序】 
 * 基本思想:堆排序是一种树形选择排序,是对直接选择排序的有效改进。
 * 堆的定义如下:具有n个元素的序列(h1,h2,...,hn),当且仅当满足(hi>=h2i,hi>=h2i+1)或(hi<=h2i,hi<=2i+1)(i=1,2,...,n/2)时称之为堆。
 * 前者为最大堆,后者为最小堆,这里只讨论最大堆。
 * 
 * 由堆的定义可以看出,堆顶元素(即第一个元素)必为最大项。
 * 完全二叉树可以很直观地表示堆的结构。堆顶为根,其它为左子树、右子树。
 * 
 * 1. 将有n个元素的数组a按照最大堆的要求进行调整
 * 2. 将栈顶a[0]元素(为最大元素)与当前最大堆的最后一个元素交换。然后将前面(n-1)个数重新调整成最大堆。重复1
 * 从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。
 * 
 */
public void duipaixu(int[] array) {
	// 循环建堆
	for (int i = 0; i < array.length - 1; i++) {
		buildMaxHeap(array, array.length-1-i); // 建堆
		swap(array, 0, array.length-1-i); // 交换堆顶和最后一个元素
	}
	System.out.println(Arrays.toString(array));
}

/** 将数组元素a[0]~a[n]构建为最大堆 **/
private void buildMaxHeap(int[] arr, int n) {
	//从第一个非叶子节点开始最大堆化
	for (int i = (n - 1) / 2; i >= 0; i--) {
		//k保存正在判断的节点
		int k = i;
		//沿左右孩子中值较大者重复向下检查
		while (2*k+1 <= n) {
			//k节点的左孩子节点
			int j = 2 * k + 1;
			//找出左右孩子节点的较大者
			if (j < n && arr[j] < arr[j+1]) j++;
			//如果k节点的值小于其较大的子节点的值
			if (arr[k] < arr[j]) {
				swap(arr, k, j);	//交换他们
				k = j;
			} else {
				break;	//当前节点完成最大堆化
			}
		}
	}
}

private void swap(int[] arr, int i, int j) {
	int tmp = arr[i];
	arr[i] = arr[j];
	arr[j] = tmp;
}
                  
                

交换排序

                  
////////////////////////////////////////////   交换排序           ////////////////////////////////////////////
/** 向左冒泡 **/
public int[] maopaopaixu_l(int[] array) throws Exception {
	
	int k;
	for (int i = 0; i < array.length; i++) {
		k = 0;	//每次开始冒泡前,初始化 k 值为 0
		for (int j = array.length-1; j > i; j--) {
			if (array[j] > array[j-1]) {
				k = 1;
				int temp = array[j];
				array[j] = array[j-1];
				array[j-1] = temp;
			}
		}
		//如果 k 值为 0,表明表中记录排序完成
		if (k == 0) break;
	}
	
	System.out.println(Arrays.toString(array));
	return array;
}

/** 向右冒泡 **/
public int[] maopaopaixu_r(int[] array) throws Exception {
		
	int k;
	for (int i = 0; i < array.length; i++) {
		k = 0;	//每次开始冒泡前,初始化 k 值为 0
		for (int j = 0; j < array.length-1-i; j++) {
			if (array[j] > array[j+1]) {
				k = 1;
				int temp = array[j];
				array[j] = array[j+1];
				array[j+1] = temp;
			}
		}
		//如果 k 值为 0,表明表中记录排序完成
		if (k == 0) break;
	}
	
	System.out.println(Arrays.toString(array));
	return array;
}

/** 快速排序 **/
public void kuaisupaixu(int[] array, int left, int right) throws Exception {
	
	if (left > right) {
		return;
	}
	int i = left, j = right;
	int temp = array[i];
	while(i != j) {
		//从右边找
		while(array[j] >= temp && i < j) {
			j--;
		}
		//从左边找
		while(array[i] <= temp && i < j) {
			i++;
		}
		if (i < j) {
			int t = array[i];
			array[i] = array[j];
			array[j] = t;
		}
	}
	array[left] = array[i];
	array[i] = temp;
	
	kuaisupaixu(array, left, i-1);
	kuaisupaixu(array, i+1, right);
	System.out.println(Arrays.toString(array));
	
}
                  
                

各种排序算法时间复杂度分析: