【复习笔记】听说找工作一定要会的三种排序算法

扫到一眼牛客的算法补习班,讲到校招必会的三种排序算法?据说会这三种不一定能找到工作,但是不会这三个一定找不到工作(快 归并 堆)。


算是作为复习,手敲三种排序:


1.快速排序

比较有用的partition函数,能够取出最小的k个元素。

partition函数里slow指针指向的是第一个大于游标的元素。交换游标跟slow指向的元素返回slow即为游标的位置。

因为是切分树结构,所以时间复杂度O(nlgn)。快速排序是非稳定的。

import java.util.Random;

public class quickSort {

	public void Sort(int [] array, int start, int end){
		if(start >= end) return;
		int mid = partition(array, start, end);
		Sort(array, start, mid - 1);
		Sort(array, mid + 1, end);
	}
	
	public static int partition(int [] array, int start, int end){
        Random random = new Random();
        //生成[start, end]之间的随机数
        int index = random.nextInt(end)%(end - start + 1) + start;
        swap(array, index, end);
        
        int quick = start, slow = start;
        
        while(quick < end){
        	if(array[quick] <= array[end]){
        		if(quick != slow){
        			swap(array, quick, slow);
        		}
        		quick++;
        		slow++;
        	}else{
        		quick++;
        	}
        }
        
        swap(array, slow, end);
		
        return slow;
	}
	
	public static void swap(int [] array, int indexa, int indexb){
		int temp = array[indexa];
		array[indexa] = array[indexb];
		array[indexb] = temp;
	}
}

2.归并排序

这里写出二路归并排序,两两分组比较,思想应用场景见《剑指Offer》——数组中的逆序对。

归并排序是稳定排序,且也是树形切分,复杂度O(nlgn)。

public class mergeSort {

	public void Sort(int [] array, int start, int end){
		int startA = start, endA = (start + end)/2;
		int startB = endA + 1, endB = end;
		if(end <= start)
			return;
		Sort(array, startA, endA);
		Sort(array, startB, endB);
		Merge(array, startA, endA, startB, endB);
	}
	
	public static void Merge(int [] array, int sa, int ea, int sb, int eb){
		
		int i = sa, k = sb, index = 0;
		int [] temp = new int [array.length];
		
		while(i <= ea && k <= eb){
			if(array[i] < array[k]){
				temp[index++] = array[i++];
			}else{
				temp[index++] = array[k++];
			}
		}
		
		while(i <= ea)
			temp[index++] = array[i++];
		while(k <= eb)
			temp[index++] = array[k++];
		
		for(int t = 0, r = sa; t < index; ++t, ++r){
			array[r] = temp[t];
		}
	}
}

3.堆排序

挺有意思的一种排序,分两个步骤

1)先建立最大堆,从倒数第一个有孩子的节点开始往上调整;

2)每次把堆顶放在已经排序的数组的第一位。

public class heapSort {

	public static void Sort(int [] array){
		buildMaxHeap(array, array.length - 1);
		System.out.println(Arrays.toString(array));
		for(int i = array.length - 1; i >= 1; --i){
			int tempnum = array[0];
			array[0] = array[i];
			array[i] = tempnum;
			maxHeapAdj(array, 0, i);
		}
	}
	
	public static void maxHeapAdj(int [] array, int from, int tol){
		//调整的节点为from节点,每次跟自己的左右孩子的最大的比较,然后下移
		//节点的左右孩子的下标分别为2i+1,2i+2
		int temp = array[from];
		int k = 2*from + 1;
		while(k < tol){
			if(k + 1 < tol && array[k] < array[k + 1])
				k++;
			//左右孩子里较大的那个都比待调整节点小,则现在的位置就是待调整的位置
			if(array[k] < temp)
				break;
			array[from] = array[k];
			from = k;
			k = 2*from + 1;
		}
		array[from] = temp;
	}
	
	//建立最大堆的过程,所有的叶子节点认为是已经合理的堆,调整节点是从第一个有孩子的节点开始调整。
	public static void buildMaxHeap(int [] array, int tol){
		for(int i = tol/2 + 1; i >=0; --i){
			maxHeapAdj(array, i, tol);
		}
	}

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值