基础排序算法总结

一:插入排序
二:选择排序
三:交换排序
四:归并排序
五:基数排序

插入排序:(直接插入排序,shell排序)
1:直接插入排序
     把左边作为已经排序好的数组,新加入的数组值和左边的数组最右边数值比较,直到不大于左边的数时停止,循环完成。最优的时间复杂度为O(n),最大时间复杂度为O(n^2),平均时间复杂度为O(n^2),是稳定的算法。

java实现代码:
package com.hdw.sort;

public class InsertSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		insertSort(a);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
	}

	private static void insertSort(int[] a) {
		// TODO Auto-generated method stub
		for(int i=1; i<a.length; i++){
			int temp;
			for(int j=i; j>=1; j--){
				if(a[j]<a[j-1]){
					temp = a[j];
					a[j] = a[j-1];
					a[j-1] = temp;
				}else{
					break;
				}
			}
		}
	}

}


2:shell排序
     是对于直接插入排序的优化,shell排序中d的选取很重要,不同的时代的人对于d的选取有不同的看法,有d=2*n-1、d=3*n+1、d=5n-1,但是不管怎么选,d=1,必须要存在,这保证了排序的正确性,她的妙处在于把相邻d的数排序好,改进了对于d=1的压力,最优时间复杂度为O(n),最坏时间复杂度为O(n^2),平均时间复杂度为O(n^1.3),这个1.3是科学家算出来的,为不稳定算法。

java代码实现
package com.hdw.sort;

public class ShellSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		print(a);
		shellSort(a);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
		System.out.println();
	}

	private static void shellSort(int[] a) {
		// TODO Auto-generated method stub
		//第一层循环是对于d的选取
		for(int d=a.length/2; d>0; d/=2){
			//第二层循环是让第d个数后的每一个数和前面相差d的数做插入排序
			for(int i=d; i<a.length; i++){
				int temp;
				//相差d的数做插入排序
				for(int j=i; j>=d; j-=d){
					if(a[j]<a[j-d]){
						temp = a[j];
						a[j] = a[j-d];
						a[j-d] = temp;
					}else{
						break;
					}
				}				
			}
			print(a);
		}


	}

}


选择排序:(直接选择排序,堆排序)
1:直接选择排序
     把数组中最大(最小)的值,选出放在数组的开头,后面有从2到n中选出最大(最小)数放到小标为2的数中,最优,最坏,平均时间复杂度均为O(n^2),不稳定算法

java代码实现
package com.hdw.sort;

public class SelectSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		selectSort(a);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
	}

	private static void selectSort(int[] a) {
		// TODO Auto-generated method stub
		for(int i=0; i<a.length-1; i++){
			int temp=a[i];
			int flag = i;
			for(int j=i+1; j<a.length; j++){
				if(a[j]<temp){
					temp = a[j];
					flag = j;
				}
			}
			a[flag] = a[i];
			a[i] = temp;
		}
	}

}


2:堆排序
     首先建立一个二叉树,把数组想象成二叉树,第一个步骤就是建立一个大顶推(小顶堆)的二叉树,第二部就是把大顶推(小顶堆)放在数组最后面一位,接下来的数再建立大顶堆(小顶堆),循环结束,最优、最差、平均时间算法O(nlog2n),不稳定算法。

java代码实现
package com.hdw.sort;

public class HeapSort {
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		heapSort(a);
		print(a);
	}

	private static void heapSort(int[] a) {
		// TODO Auto-generated method stub
		for(int i=a.length-1; i>0; i--){
			createMaxHeap(a,i);
			swap(a,0,i);
		}
		
		
	}

	private static void swap(int[] a, int i, int j) {
		// TODO Auto-generated method stub
		a[i] = a[i] + a[j];
		a[j] = a[i] - a[j];
		a[i] = a[i] - a[j];
	}

	private static void createMaxHeap(int[] a,int lastIndex) {
		// TODO Auto-generated method stub
		for(int i=(lastIndex-1)/2; i>=0; i--){
			int k = i;
			//对K下面的树建立大顶推
			while(2*k+1<=lastIndex){
				//假使最大数的下标为2*k+1
				 int maxIndex = 2*k+1;
				 //如果存在右子树则比较,选择较大数的下标,为下面和父节点比较
				 if(maxIndex < lastIndex){
					 if(a[maxIndex] < a[maxIndex+1]){
						 maxIndex++;
					 }
				 }
				 //直接子节点和父节点比较,若需要交换则把k换为最大子节点的下标,好向下递推建立大顶推树,否则直接退出while循环
				 if(a[k] < a[maxIndex]){
					 swap(a, k, maxIndex);
					 k = maxIndex;
				 }else{
					 break;
				 }
			}
		}
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
	}

}


交换排序:
1:冒泡排序
     相邻两个数进行比较把大的数放在右边,循环后最大的数再数组的最右边,对剩余n-1个数使用同样的方法,最优时间复杂度O(n),最差时间复杂度O(n^2),平均时间复杂度为O(n^2),稳定算法。

java代码实现
package com.hdw.sort;

public class BubbleSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//int[] a = {9,2,7,6,4,8,1,3,5};
		int[] a = {1,2,3,4,5,6};
		print(a);
		bubbleSort(a);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
		System.out.println();
	}

	private static void bubbleSort(int[] a) {
		// TODO Auto-generated method stub		
		for(int i=0; i<a.length-1; i++){
			boolean flag = false;
			for(int j=0; j<a.length-1-i; j++){				
				int temp=a[j];
				if(a[j]>a[j+1]){
					a[j] = a[j+1];
					a[j+1] = temp;
					flag = true;
				}
			}
			if(!flag){
				break;
			}
			print(a);
		}

	}

}


2:快速排序
     快速排序是对于冒泡排序的改进,把中间值作为一个key,左边放的是比key小的值,右边是比key大的值,然后key左边的数进行快排,右边也进行快排,递归结束,最优时间复杂度为O(nlog2n),最差时间复杂度为O(n^2),平均时间复杂度为O(nlog2n),不稳定算法

java代码实现
package com.hdw.sort;

public class QuickSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		print(a);
		quickSort(a,0,a.length-1);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
		System.out.println();
	}
	
	private static void quickSort(int[] a, int left,int right){
		//当可以进行快排时
		if(left < right){
			//把最左边的值设为key,把left的值赋给low,right的值赋给high
			int key = a[left];
			int low = left;
			int high = right;
			//当low<high时,循环把比key更大的放在它右边,比key更小的值放在它的左边
			while(low<high){
				//如果右边的值大于key则一直向后对比
				while(low < high && a[high] >= key){
					high--;
				}
				//符合是把高位的值赋给低位的值
				a[low] = a[high];
				//如果左边的值一直小于key则一直向前对比
				while(low < high && a[low] < key){
					low++;
				}
				//把地位的值赋值给高位
				a[high] = a[low];
			}
			//把key的值赋给指针停止的地方
			a[low] = key;
			quickSort(a,left,low-1);
			quickSort(a,low+1,right);				
		}
	}

}


归并排序:
     把数组每两个进行比较,比较完了以后作为一个整体,在两个整体之间的比较,循环下去,直到结束,我采用的是递归算法,真个数组分为两个部分,左边归并,右边也归并,最优、最差、平均时间负杂度为O(nlog2n),需要辅助空间为O(n),稳定算法

java代码实现
package com.hdw.sort;

public class MergeSort {
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {9,2,7,6,4,8,1,3,5};
		int[] temp = new int[a.length];
		mergeSort(a,0,a.length-1,temp);
		print(a);
	}


	private static void mergeSort(int[] a, int first, int last, int[] temp) {
		// TODO Auto-generated method stub
		if(first < last){
			int mid = (first + last) / 2;
			mergeSort(a,first,mid,temp);
			mergeSort(a,mid+1,last,temp);
			mergeArray(a,first,mid,last,temp);
		}
	}


	private static void mergeArray(int[] a, int first, int mid, int last,
			int[] temp) {
		// TODO Auto-generated method stub
		int i = first;
		int j = mid + 1;
		int m = mid;
		int n = last;
		int k = 0;
		while(i <= m && j <= n){
			if(a[i] < a[j]){
				temp[k++] = a[i++];
			}else{
				temp[k++] = a[j++];
			}
		}
		while(i <= m){
			temp[k++] = a[i++];
		}
		while(j <= n){
			temp[k++] = a[j++];
		}
		for(i = 0; i < k; i++){
			a[first+i] = temp[i];
		}
		
	}


	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
	}

}


基数排序:
     d为数组的最大位数,r为可区分每个数的基数的位数,比如数组里面的是整数则r=9,范围0-9,英文字母则为26,a-z,先把个位数排序,放在一个辅助的数组空间里,在把辅助空间里面值赋值给原数组,接着是百位数排序,重复,知道所有位数排序完,如果位数r比较大时,则从高位开始排序,最优时间复杂度为O(d(r+n)),最差时间复杂度为O(d(n+rd)),平均O(d(r+n)),需要辅助空间O(rd+n)

java代码实现

package com.hdw.sort;

import java.util.Arrays;

public class RadixSort {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] a = {1100, 192, 221, 12, 23};
		print(a);
		radixSort(a,10,4);
		print(a);
	}

	private static void print(int[] a) {
		// TODO Auto-generated method stub
		for (int i : a) {
			System.out.print(i+",");
		}
		System.out.println();
	}

	/******************************************************** 
	*函数名称:radixSort 
	*参数说明:需要排序的数组  
	*          radix表示 基数的大小
	*          distance表示最高位数的大小
	*说明:    通过基数排序把数组排好
	*********************************************************/
	private static void radixSort(int[] a, int radix, int distance) {
		// TODO Auto-generated method stub
		//缓存数组
		int[] temp = new int[a.length];
		//存储不同小标的个数
		int[] count = new int[radix];
		//设置每次求数组数除于的数
		int rate = 1;
		//把每一个位数的数比较		
		for(int i=0; i<distance; i++){
			//把数组a的值赋值给temp数组
			System.arraycopy(a, 0, temp, 0, a.length);
			//初始化数组count每个值为0
			Arrays.fill(count, 0);
			
			//统计小标为key的值的个数
			for(int j=0; j<a.length; j++){
				int key = (temp[j]/rate)%radix;
				count[key]++;
			}
			//对count的值进行相加,这里j是小于radix,不是a.length
			for(int j=1; j<radix; j++){
				count[j] += count[j-1];
			}
			//进行数组的交换
			for(int m=a.length-1; m>=0; m--){
				int subkey = (temp[m]/rate)%radix;
				count[subkey]--;
				a[count[subkey]] = temp[m];				
			}
			//对下面一个位数排序
			rate*=radix;
			print(a);
		}
	}
		
		
		

}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章