八大排序算法的Java实现

插入排序

直接插入排序:稳定排序,时间复杂度:O(n)~O(n^2),适用于少量元素。基本思想:将一个元素插入到已排好序的列表中。

	public static void insertsort(int[] array){
		int n = array.length;
		for(int i=1;i<n;i++){
			int j = i-1;
			int key = array[i];
			while(j>=0 && array[j]>key){
				array[j+1] = array[j];
				j--;
			}
			array[j+1] = key;
		}
	}

Shell排序:不稳定,O(nlogn),基本思想:把整个列表分成若干个子序列分别进行直接插入排序

	/*
	 * Shell排序调用的直接插入排序方法,当gap=1时等同于上一个方法
	 */
	private static void insertsort(int[] array,int gap){
		int n = array.length;
		for(int i=gap;i<n;i++){
			int j = i-gap;
			int key = array[i];
			while(j>=0 && array[j]>key){
				array[j+gap] = array[j];
				j-=gap;
			}
			array[j+gap] = key;
		}
	}
	
	public static void shellsort(int[] array){
		int n = array.length;
		int dk = n/2;
		while(dk>=1){
			Sort.insertsort(array, dk);
			dk /= 2;
		}
	}

选择排序

简单选择排序:不稳定,O(n^2),每次选择未排序列表中最小的元素与第一个数交换位置。

	public static void selectsort(int[] array){
		int n = array.length;
		for(int i=0;i<n;i++){
			int key = getMin(array,i,n);
			if(key != i){
				int temp = array[key];
				array[key] = array[i];
				array[i] = temp;
			}
		}
	}
	
	private static int getMin(int[] array,int low,int high){
		int temp = low;
		for(int i=low+1;i<high;i++){
			if(array[i] < array[temp]){
				temp = i;
			}
		}
		return temp;
	}

堆排序:不稳定,O(nlogn),建最大堆,每次将堆顶元素与最后一个元素交换,再建堆,以此类推。

	/*
     * 堆排序: 调整堆,array[s...array.length-1]是除array[s]外满足大顶堆的堆
     */
     private static void heapAdjust(int[] array, int s,int length){
           int child = s*2+1;
           int temp = array[s];
           while(child<length){
                  if((child+1)<length && array[child+1]>array[child]){
                         child++;
                  }
                  if(array[child]>array[s]){
                         array[s] = array[child];
                         array[child] = temp;
                         s = child;
                         child = child*2 + 1;
                         temp = array[s];
                  }else{
                         break;
                  }
           }
     }
    
     private static void biuldingHeap(int[] array){
           int length = array.length;
           for(int i=length/2;i>-1;i--){
                  heapAdjust(array,i,length);
           }
     }
    
     public static void heapSort(int[] array){
           biuldingHeap(array);
           for(int i=array.length-1;i>-1;i--){
                  int temp = array[i];
                  array[i] = array[0];
                  array[0] = temp;
                  heapAdjust(array,0,i);
           }
     }

交换排序

冒泡排序:稳定排序,O(n^2),基本思想:对未排序范围内的数,从上到下,相邻的数两两比较,让较大的数往下沉。

	public static void bubbleSort(int[] array){
           for(int i=array.length-1;i>0;i--){
                  for(int j=0;j<i;j++){
                         if(array[j]>array[j+1]){
                               int temp = array[j+1];
                               array[j+1] = array[j];
                               array[j] = temp;
                         }
                  }
           }
     }

快速排序:不稳定排序,O(nlogn),选择基准元素(通常第一个),比它大的放右边,比它小的放左边,依次类推。

	public static void quickSort(int[] array, int low, int high){
           if(low<high){
                  int privotLoc = partition(array, low, high);
                  quickSort(array,low,privotLoc-1);
                  quickSort(array,privotLoc+1,high);
           }
     }
    
     private static int partition(int[] array, int low, int high){
           int privotKey = array[high];
	        for (int i = low; i < high; i++) {
	        	if (array[i] < privotKey) {
	        		swap(array, i, low++);
	        	}
	        }
	        swap(array, high, low);
	        return low;
     }
    
     private static void swap(int[] array,int a,int b){
           int temp = array[a];
           array[a] = array[b];
           array[b] = temp;
     }

归并排序

稳定排序,O(nlogn),基本思想:将两个有序列表合并为一个有序列表。

	/*
      * 归并排序
      * @param array
      * @param s
      * @param len 每次归并的有序集合的长度
      */
      public static void mergeSort(int[] array, int low, int high){
            int mid = (low + high)/2;
            if(low<high){
            	mergeSort(array, low, mid);
            	mergeSort(array, mid+1, high);
            	merge(array, low, mid+1, high);
            }
      }
     
      /*
      * 二路归并:将两个有序表合成一个有序表
      * @param a
      * @param s 第一个有序表的起始下标
      * @param m 第二个有序表的起始下标
      * @param t 第二个有序表的结束下标
      */
      private static void merge(int[] a, int s, int m, int t){
            int[] temp = new int[t-s+1];
            int i=s,j=m,k=0;
            while(i<m && j<=t){
                   if(a[i]<=a[j]){
                          temp[k] = a[i];
                          i++;
                          k++;
                   }else{
                          temp[k] = a[j];
                          j++;
                          k++;
                   }
            }
            while(i<m){
                   temp[k] = a[i];
                   k++;
                   i++;
            }
            while(j<=t){
                   temp[k] = a[j];
                   k++;
                   j++;
            }
            System.arraycopy(temp, 0, a, s, temp.length);
      }

基数排序

稳定排序,O(logR(b)),从个位开始,每次依据该位上的数字将不同的元素放入不同的桶中,达到排序的目的。

	public static void radixSort(int[] array, int d){
    	  int k=0;
    	  int n=1;  //用以获取基数的除数
    	  int m=1;  //控制排序在哪一位
    	  int[][] temp = new int[10][array.length];	//数组的第一维表示可能的余数0~9
    	  while(m<=d){
    		  int[] order = new int[10]; //数组order[i]用来表示该位是i的数的个数
    		  for(int i=0;i<array.length;i++){
    			  int lsd = (array[i]/n) % 10;
    			  temp[lsd][order[lsd]] = array[i];
    			  order[lsd]++;
    		  }
    		  for(int i=0;i<10;i++){
    			  if(order[i]!=0){
    				  for(int j=0;j<order[i];j++){
    					  array[k++] = temp[i][j];
    				  }
    			  }
    		  }
    		  n = n * 10;
    		  k=0;
    		  m++;
    	  }
      }

小结:

  • 稳定排序:冒泡、直接插入、归并、基数排序。
  • 排序方法中,最好情况和最坏情况都一样的是选择排序和堆排序,不管初始序列是否有序。
  • 排序的时间复杂度下限是O(nlogn)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值