常用排序算法(插入排序,快速排序,归并排序,堆排序)

选择排序和冒泡排序

冒泡排序和选择排序的原理和实现比较类似,冒泡排序是按次序将序列中相邻的元素比较,符合条件时交换两者的位置,最后在序列的末尾有一个最大值,除去末尾的数组成新的序列,重复前面的步骤。选择排序是将序列中每个元素和暂存元素进行比较,符合条件时将临时变量和序列中元素交换,最后将最优值(最大或最小)的元素循环地取出。

插入排序

插入排序的概念,就像平时玩扑克一样,将后面来的数插入到前面序列中,在后面的一张插入的时候,前面的序列已经是有序的了。


public class InsertSort {
	public static void insertSort(int[] a){
	    int i, j;
	    int n =a.length;
	    int target;
		for (i = 1; i < n; i++) {
		   j = i;
		    target = a[i];
		    while (j > 0 && target < a[j-1])
		    {
		        a[j] = a[j-1];
		        j--;
		    }
		    a[j] = target;
		}
	}
	public static void main(String[] args){
		int[]  a={1,5,9,4,10,8,7};
		insertSort(a);
		for(int i= 0;i<a.length;i++){
			System.out.print(a[i]+",");
		}
	}
}


快速排序

快速排序是在序列中选取一个中间值,是左边的数全部不大于(不小于)这个中间值,右边的数全部不小于(不大于)这个数。使整个序列分成左右两个分序列,然后又对这两个分序列按上述规则处理,一直递归下去,直到分序列的元素数不少于一个(不需要再划分了)。



public class QuickSort {
	public static int gerMark(int[] a, int left ,int right){
		int mark = a[left];
		while(left<right){
			while(left<right&&mark<a[right]){
				right--;
			}
			a[left]=a[right];
			while(left<right&&mark>a[right]){
				left++;
			}
			a[right]=a[left];
		}
		a[left]= mark;
		return left;
	}
	
	public static void quickSort(int[] a, int left ,int right){
		if(left<right){
			int middle = gerMark(a,left,right);
			quickSort(a,left,middle-1);
			quickSort(a,middle+1,right);
		}
	}
	
	public static void main(String[] args){
		
		int[] a={7,2,5,4,12};
		quickSort(a,0,a.length-1);
		for(int i= 0;i<a.length;i++){
			System.out.print(a[i]+",");
		}
	}
}


归并排序

归并排序也是以递归的方式进行排序,但是它是插入排序的延伸,我们要以递归的逆过程和插入排序的延伸(插入排序是一个一个插入,归并排序是一组数据插入另一组数据)来思考,首先可以想象,一个根节点包含这组数,经过不断地递归划分成为一个二叉树,每个节点都只有一个元素,再一层一层地向上按插入排序的逻辑重新排序每个节点中的一组数,最后的根节点中的序列就有序了。



public class MergeSort {

	public  static int[] mergeSort(int[] a, int left,int right){
		int middle = (left+right)/2;
		if(left<right){
			mergeSort(a,left,middle);
			mergeSort(a,middle+1,right);
			merge(a,left,middle,right);	
		}
		return a;
	}
	
	public static void merge(int[] a ,int left ,int middle,int right){
		int[] temp = new int[right-left+1];
		int i=left;
		int j=middle+1;
		int k=0;
		while(i<=middle&&j<=right){
			if(a[i]<a[j]){
				temp[k++]=a[i++];
			}
			else{
				temp[k++]=a[j++];
			}
		}	
		while(i<=middle){
			temp[k++]=a[i++];
		}
		while(j<=right){
			temp[k++]=a[j++];
		}
		for(int m=0;m<temp.length;m++){
			a[left+m] = temp[m];
		}
	}
	
	public static void main(String[] args){
	    int[] a={8,99,37,10,51,109};
		mergeSort(a,0,a.length-1);
		for(int i= 0;i<a.length;i++){
			System.out.print(a[i]+",");
		}
	}
}


堆排序

堆就是满足一定条件的完全二叉树,大根堆的这个条件就是父节点的值不小于左右子节点的值。它的值是按从上往下,从左往右的顺序(从1开始)。左子节点的值=父节点值* 2,而右节点值= 父节点值*2+1。

堆排序的算法过程是按照序列顺序生成一个堆,随后从根节点从上至向从左至开始不断的调整堆使其形成一个最大堆,然后取出根节点就是该序列的最大值,对剩下来的子序列进行调整,又形成最大堆。重复上面的步骤,直到堆中元素只有一个。整体来说堆排序包括调整堆,形成最大堆。

public class HeapSort {

	public static void heapSort(int[] data){
		buildMaxHeap(data);
		for (int i = data.length; i > 1; i--) {
            int tmp = data[0];
            data[0] = data[i - 1];
            data[i - 1] = tmp;
            adjustHeapify(data, 1, i - 1);
	    }
	}
 
	/*
	 * 形成最大堆
	 */
	private static void buildMaxHeap(int[] data){
		for(int i=data.length/2;i>0;i--){
			adjustHeapify(data,i,data.length);
		}	
	}
	
	/*
	 * 调整堆
	 * @Parameter 序列data,父节点序号i,堆大小heapSize
	 */
	private static void adjustHeapify(int[] data,int i,int heapSize){
		int l=i*2;
		int r=i*2+1;
		int largest=i;

        // 如果左子节点大于父节点,则将左子节点作为最大节点
        if (l <= heapSize && data[l-1]>data[i-1]) {
            largest = l;
        }

        // 如果右子节点比最大节点还大,那么最大节点应该是右子节点
        if (r <= heapSize && data[r-1]>data[largest-1]) {
            largest = r;
        }
        
		if(largest!=i){
			int temp=data[largest-1];
			data[largest-1]=data[i-1];
			data[i-1]=temp;
			adjustHeapify(data,largest,heapSize);//重复比较
		}		
	}
	
	public static void main(String[] args){
		int [] data={4,1,3,2,16,9,10,14,8,7};
	
		heapSort(data);
		for(int i=0;i<data.length;i++){
			System.out.print(data[i]+",");
		}
	}
}

对上述代码执行后的结果如下

原文地址:https://www.cnblogs.com/sweiqi/p/5933342.html