java----八種排序算法


1.直接插入排序

經常碰到這樣一類排序問題:把新的數據插入到已經排好的數據列中。

將第一個數和第二個數排序,然后構成一個有序序列

將第三個數插入進去,構成一個新的有序序列。

對第四個數、第五個數……直到最后一個數,重復第二步。

如何寫成代碼:

首先設定插入次數,即循環次數,for(int i=1;i<length;i++),1個數的那次不用插入。

設定插入數和得到已經排好序列的最后一個數的位數。insertNum和j=i-1。

從最后一個數開始向前循環,如果插入數小於當前數,就將當前數向后移動一位。

將當前數放置到空着的位置,即j+1。

 

代碼實現如下:

 或者內部是2個for形式

 

    public static void insertSort(int[] a){
        if(a.length>1){
            int insertNum;
            //下標0的默認是有序,后面的都是要插入的數
            for(int i=1;i<a.length;i++){
                insertNum = a[i];
                //i-1個都是有序的
                int j=i-1;
                for(;j>=0;j--){
                    //待插的數比前面小,就后一位
                    if(insertNum<a[j]){
                        a[j+1]=a[j];
                    }else{
                        //否則停止移動
                        break;
                    }
                }
                
                a[j+1]=insertNum;
            }
        }
        
    }
View Code

 

2.希爾排序

 

對於直接插入排序問題,數據量巨大時。

將數的個數設為n,取奇數k=n/2,將下標差值為k的書分為一組,構成有序序列。

再取k=k/2 ,將下標差值為k的書分為一組,構成有序序列。

重復第二步,直到k=1執行簡單插入排序。

如何寫成代碼:

首先確定分的組數。

然后對組中元素進行插入排序。

然后將length/2,重復1,2步,直到length=0為止。

 注意:第一趟32,23,5一組 和 43,13一組,組內直接插入排序

代碼實現如下:

 或者

    public static void shellSort(int[] a){
        if(a.length>1){
           int len=a.length;
           while(len>0){
               len/=2;
               for(int i=0;i<len;i++){//分的組
                   for(int j=i+len;j<a.length;j+=len){//組中的元素,除了第一個元素
                       //組內直接插入排序
                       int t=j-len; //組內第一個元素默認有序
                       int insertNum=a[j];
                        for(;t>=0;t-=len){
                            //待插的數比前面小,就后一位
                            if(insertNum<a[t]){
                                a[t+len]=a[t];
                            }else{
                                //否則停止移動
                                break;
                            }
                        }
                        
                        a[t+len]=insertNum;
                        
                   }
               }
//                 for(int a1 :a)
//                     System.out.print(a1+"-");
//                 System.out.println();
           }
        }
    }
View Code

 

3.簡單選擇排序

 

常用於取序列中最大最小的幾個數時。

(如果每次比較都交換,那么就是交換排序;如果每次比較完一個循環再交換,就是簡單選擇排序。)

遍歷整個序列,將最小的數放在最前面。

遍歷剩下的序列,將最小的數放在最前面。

重復第二步,直到只剩下一個數。

如何寫成代碼:

首先確定循環次數,並且記住當前數字和當前位置。

將當前位置后面所有的數與當前數字進行對比,小數賦值給key,並記住小數的位置。

比對完成后,將最小的值與第一個數的值交換。

重復2、3步。

 

代碼實現如下:

 

 

4.堆排序

 

對簡單選擇排序的優化。

將序列構建成大頂堆。

將根節點與最后一個節點交換,然后斷開最后一個節點。

重復第一、二步,直到所有節點斷開。

代碼實現如下:

 

public  void heapSort(int[] a){
       System.out.println("開始排序");
       int arrayLength=a.length;
       //循環建堆  
       for(int i=0;i<arrayLength-1;i++){
           //建堆  

           buildMaxHeap(a,arrayLength-1-i);
           //交換堆頂和最后一個元素  
           swap(a,0,arrayLength-1-i);
           System.out.println(Arrays.toString(a));
       }
   }
   private  void swap(int[] data, int i, int j) {
       // TODO Auto-generated method stub  
       int tmp=data[i];
       data[i]=data[j];
       data[j]=tmp;
   }
   //對data數組從0到lastIndex建大頂堆  
   private void buildMaxHeap(int[] data, int lastIndex) {
       // TODO Auto-generated method stub  
       //從lastIndex處節點(最后一個節點)的父節點開始  
       for(int i=(lastIndex-1)/2;i>=0;i--){
           //k保存正在判斷的節點  
           int k=i;
           //如果當前k節點的子節點存在  
           while(k*2+1<=lastIndex){
               //k節點的左子節點的索引  
               int biggerIndex=2*k+1;
               //如果biggerIndex小於lastIndex,即biggerIndex+1代表的k節點的右子節點存在  
               if(biggerIndex<lastIndex){
                   //若果右子節點的值較大  
                   if(data[biggerIndex]<data[biggerIndex+1]){
                       //biggerIndex總是記錄較大子節點的索引  
                       biggerIndex++;
                   }
               }
               //如果k節點的值小於其較大的子節點的值  
               if(data[k]<data[biggerIndex]){
                   //交換他們  
                   swap(data,k,biggerIndex);
                   //將biggerIndex賦予k,開始while循環的下一次循環,重新保證k節點的值大於其左右子節點的值  
                   k=biggerIndex;
               }else{
                   break;
               }
           }
       }
   }

 

 

5.冒泡排序

 

一般不用。

將序列中所有元素兩兩比較,將最大的放在最后面。

將剩余序列中所有元素兩兩比較,將最大的放在最后面。

重復第二步,直到只剩下一個數。

 

 

如何寫成代碼:

設置循環次數。

設置開始比較的位數,和結束的位數。

兩兩比較,將最小的放到前面去。

重復2、3步,直到循環次數完畢。

 

代碼實現如下:

 

6.快速排序

 

要求時間最快時。

選擇第一個數為p,小於p的數放在左邊,大於p的數放在右邊。

遞歸的將p左邊和右邊的數都按照第一步進行,直到不能遞歸。

 

 

代碼實現如下:

 

 

7.歸並排序

 

速度僅次於快排,內存少的時候使用,可以進行並行計算的時候使用。

選擇相鄰兩個數組成一個有序序列。

選擇相鄰的兩個有序序列組成一個有序序列。

重復第二步,直到全部組成一個有序序列。

 

代碼實現如下:

 

public static void mergeSort(int[] numbers, int left, int right) {  
   int t = 1;// 每組元素個數  
   int size = right - left + 1;  
   while (t < size) {  
       int s = t;// 本次循環每組元素個數  
       t = 2 * s;  
       int i = left;  
       while (i + (t - 1) < size) {  
           merge(numbers, i, i + (s - 1), i + (t - 1));  
           i += t;  
       }  
       if (i + (s - 1) < right)  
           merge(numbers, i, i + (s - 1), right);  
   }  
}  
private static void merge(int[] data, int p, int q, int r) {  
   int[] B = new int[data.length];  
   int s = p;  
   int t = q + 1;  
   int k = p;  
   while (s <= q && t <= r) {  
       if (data[s] <= data[t]) {  
           B[k] = data[s];  
           s++;  
       } else {  
           B[k] = data[t];  
           t++;  
       }  
       k++;  
   }  
   if (s == q + 1)  
       B[k++] = data[t++];  
   else  
       B[k++] = data[s++];  
   for (int i = p; i <= r; i++)  
       data[i] = B[i];  
}

 

8.基數排序

 

用於大量數,很長的數進行排序時。

將所有的數的個位數取出,按照個位數進行排序,構成一個序列。

將新構成的所有的數的十位數取出,按照十位數進行排序,構成一個序列。

 

代碼實現如下:

 

public void sort(int[] array) {
       //首先確定排序的趟數;    
       int max = array[0];
       for (int i = 1; i < array.length; i++) {
           if (array[i] > max) {
               max = array[i];
           }
       }
       int time = 0;
       //判斷位數;    
       while (max > 0) {
           max /= 10;
           time++;
       }
       //建立10個隊列;    
       List<ArrayList> queue = new ArrayList<ArrayList>();
       for (int i = 0; i < 10; i++) {
           ArrayList<Integer> queue1 = new ArrayList<Integer>();
           queue.add(queue1);
       }
       //進行time次分配和收集;    
       for (int i = 0; i < time; i++) {
           //分配數組元素;    
           for (int j = 0; j < array.length; j++) {
               //得到數字的第time+1位數;  
               int x = array[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
               ArrayList<Integer> queue2 = queue.get(x);
               queue2.add(array[j]);
               queue.set(x, queue2);
           }
           int count = 0;//元素計數器;    
           //收集隊列元素;    
           for (int k = 0; k < 10; k++) {
               while (queue.get(k).size() > 0) {
                   ArrayList<Integer> queue3 = queue.get(k);
                   array[count] = queue3.get(0);
                   queue3.remove(0);
                   count++;
               }
           }
       }

 

 

----[轉自微信公眾號] 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM