­

Java數據結構與演算法–簡單排序

  • 2019 年 11 月 21 日
  • 筆記

版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/wangtongxue123456/article/details/72638485

簡單排序

本文討論比較簡單的排序演算法:冒泡排序、選擇排序、插入排序

三個演算法都包括如下兩個步驟。

  • 比較兩個數據項
  • 交換兩個數據項、或複製其中一項。

冒泡排序

冒泡排序演算法運行起來非常慢,但是在概念上他是排序演算法中最簡單的。

冒泡排序遵循的規則: 1. 比較兩個數據 2. 如果左邊的數據大,則兩個數據交互位置。 3. 向右移動一個位置,比較下面兩個數據。(沿著這個隊列一直比較下去,一直比較到隊列的最右端),這時最右端的數據應該會是最大的數。 4. 當碰到第一個排定的數據後,就返回隊列的左端重新開始下一趟排序。 程式碼實現

/**   * 冒泡排序   */  public class BubbleSort {      //初始化數組      private static long a[]=new long[]{11,4,7,9,2,10,23,8,34,29};      //數組長度      private static int nElems=a.length;      public static void main(String[] args) {          int in,out;          for (out=nElems-1;out>1;out--){ //              for (in=0;in<out;in++){                  //比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。                  if (a[in]>a[in+1]){                      swap(in,in+1);                  }              }          }          //輸出排序          for (long l:a){              System.out.print(l+" ");          }      }      //交換數據      private static void swap(int in, int i) {          long temp=a[in];          a[in]=a[in+1];          a[in+1]=temp;      }

演算法思路 1.將最小的數據項放在數組的最開始,並將最大的數據項放在數組的最後。 2.外層for 循環的計數器out從數組的最後開始,沒經過一次循環out減一。下標大於out的數據項都是已經排好序的,變數out每完成一次內部循環(計數器為in)後就左移一位。 3.內層for循環計數器in從數組的最開始算起(in=0),沒完成一次內部循環體加一,當它等於out時結束一次循環,在內層for循環體重,數組下標in和in+1的兩個數據項進行比較,如果in數據大於in+1數據項,則交換數據。 4.為了清晰增加獨立的swap()方法執行交換,但是它會增加一些額外的消耗,如果自己使用排序程式,最好將交換操作這段程式碼直接放到程式中。這樣可以提高一些速度。

選擇排序

選擇排序(Selection sort)是一種簡單直觀的排序演算法。它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的數據元素排完。 選擇排序是不穩定的排序方法

程式碼實現

/**   * Created by YcDr on 2017/5/24.   * 選擇排序   */  public class SelectSort {      //初始化數組      private static long a[]={12,34,19,2,54,13,11,33,18,9};      //數組長度      private static int nElems=a.length;        public static void main(String[] args) {          int in,out,temp;          for (out=0;out<nElems;out++){              temp=out;//temp臨時變數,用於存取最小值下標              for (in=out+1;in<nElems;in++){                      if (a[temp]>a[in]){                          temp=in;                      }              }              //每次循環找出最小值下標後,在進行數據交換              swap(out,temp);          }            for (long l:a)              System.out.print(l+" ");      }      //交換數據      private static void swap(int i,int t) {          long temp=a[t];          a[t]=a[i];          a[i]=temp;      }  }

與冒泡排序比較

選擇排序與冒泡排序相比,都執行了相同的比較次數N*(N-1)/2,但是相比冒泡排序,選擇排序降低了交換數據的次數。 選擇排序和冒泡排序一樣運行了O(N^2)時間,但是顯然選擇排序要比冒泡排序更快一些,因為選擇排序交換次數很少,如果交換時間及比比較時間及要大的多時,選擇排序實際要快的多。

插入排序

在大多數情況下,插入演算法是本章描述的基本排序演算法中最後的一種,雖然插入排序演算法任然需O(N^2) 的時間,但是在一般情況下他要比冒泡排序快一倍,比選擇排序還要快一點。

演算法思路 1. 默認序列中的第0個元素是有序的; 2. 從下標為1(下標從0開始)的元素開始,取當前下標i位置處的元素a[i]保存到一個臨時變數里; 3. 對前半部分有序序列的循環遍歷,並與臨時變數比較,直到遇到一個比臨時變數小的元素(這裡默認是從小到大排序),交換數據 4. 將待插入元素的下標 i 向後推移一個位置; 5. 重複進行第2步到第4步,直到亂序序列中的元素被全部插入到有序序列中;

程式碼實現

/**   * Created by YcDr on 2017/5/25.   * 插入排序   */  public class InsertSort {      //初始化數組      private static long a[]={12,19,34,2,54,13,11,33,18,9};      //數組長度      private static int nElems=a.length;        public static void main(String[] args) {          int in,out;          for (out=1;out<nElems;out++){              long temp=a[out];              in=out;              while (in>0&&a[in-1]>=temp){                  a[in]=a[in-1];                  in--;              }              a[in]=temp;          }            for (long l:a){              System.out.print(l+" ");          }      }  }

穩定性

有些時候,排序要考慮數據項擁有相同關鍵字的情況,例如,僱員姓名按字典進行排序,現在又想按郵政編碼排序,並希望,讓不需要排序的數據保持原來的排序。這種情況下,則只需要演算法對需要排序的數據進行排序,讓不需要的數據保持原來的順序,某些演算法滿足這樣的要求,他們就可以稱為穩定的演算法。