數據結構常用排序(java)

數據結構排序算法的概念是從網上抄錄的:

基本概念:

1、  排序:按照一定的關鍵字,將一個序列排列成想要得到的一個新的序列。

2、  內部排序和外部排序:整個排序過程完全在內存中進行,叫做內部排序。數據量較大需要藉助外部存儲設備才能完成,叫做外部排序。

3、  主關鍵字和此關鍵字:

4、  排序的穩定性:對於相同的元素來說,在排序之前和之後的書訊是一樣的,那麼這種排序就是穩定的排序,如果順序發生了變化,那麼就是不穩定排序。

插入類排序:

(一)   思想:在一個已經排好序的序列中,將未被排進的元素按照原先的規定插入到指定位置。

(二)   分類:

1、  直接插入排序:

①   思想:最基本的插入排序,將第i個插入到前i-1箇中的適當位置。

②   時間複雜度:T(n) = O(n)。

③   空間複雜度:S(n) = O(1)。

④   穩定性:穩定排序。循環條件while(r[0].key < r[j].key)保證的。

⑤   程序:

 /**
  * 直接插入排序:
  * 1.從第一個元素開始,該元素可以認爲已經被排序 
  * 2.取出下一個元素,在已經排序的元素序列中從後向前掃描
  * 3.如果該元素小於前面的元素(已排序),則依次與前面元素進行比較如果小於則交換,直到找到大於該元素的就則停止;
  * 4.如果該元素大於前面的元素(已排序),則重複步驟2 5.重複步驟2~4 直到所有元素都排好序 。
  * 
  * @param a
  */
 public static void insert(int[] a) {
  for (int i = 1; i < a.length; i++) {
   int key = a[i];
   for (int j = i - 1; j >= 0; j--) {
    if (key < a[j]) {
     int temp = a[j];
     a[j] = key;
     a[i] = temp;
     i = j;
    }
   }
  }
 }

2、  折半插入排序:

①   思想:因爲是已經確定了前部分是有序序列,所以在查找插入位置的時候可以用折半查找的方法進行查找,提高效率。

②   時間複雜度:比較時的時間減爲O(n㏒n),但是移動元素的時間耗費未變,所以總是得時間複雜度還是O(n)。

③   空間複雜度:S(n) = O(1)。

④   穩定性:穩定排序。

⑤   程序:

 /**
  * 折半插入排序:
  * 在將一個新元素插入已排好序的數組的過程中,尋找插入點時, 將待插入區域的首元素設置爲a[low],末元素設置爲a[high],
  * 比較時將待插入元素與a[m],其中m=(low+high)/2相比較,如果比參考元素大,
  * 則選擇a[low]到a[m-1]爲新的插入區域(即high=m-1), 否則選擇a[m+1]到a[high]爲新的插入區域(即low=m+1),
  * 如此直至low<=high不成立,即將此位置之後所有元素後移一位, 並將新元素插入a[high+1]。
  * 
  * @param a
  */
 public static void binaryInsert(int[] a) {
  // {1, 5, 5, 3, 4, 3,2}
  for (int i = 1; i < a.length; i++) {
   int key = a[i];
   int low = 0;
   int high = i - 1;
   while (low <= high) {
    int mid = (low + high) / 2;
    if (key < a[mid]) {
     high = mid - 1;
    } else {
     low = mid + 1;
    }
   }
   System.out.println("low:" + low + ",high:" + high + ",i:" + i
     + ",key:" + key);
   for (int j = i; j > high + 1; j--) {
    a[j] = a[j - 1];
   }
   a[high + 1] = key;
  }
 }

3、shell排序

交換類排序:

(一)   思想:通過交換逆序元素進行排序的方法。

(二)   分類:

1、  冒泡排序:

①   思想:反覆掃描待排序序列,在掃描的過程中順次比較相鄰的兩個元素的大小,若逆序就交換位置。第一趟,從第一個數據開始,比較相鄰的兩個數據,(以升序爲例)如果大就交換,得到一個最大數據在末尾;然後進行第二趟,只掃描前n-1個元素,得到次大的放在倒數第二位。以此類推,最後得到升序序列。如果在掃描過程中,發現沒有交換,說明已經排好序列,直接終止掃描。所以最多進行n-1趟掃描。

②   時間複雜度:T(n) = O(n)。

③   空間複雜度:S(n) = O(1)。

④   穩定性:穩定排序。

⑤   程序:

 /**
  * 冒泡排序:
  * 依次比較相鄰的兩個數,將小數放在前面,大數放在後面。 即在第一趟:首先比較第1個和第2個數,將小數放前,大數放後。
  * 然後比較第2個數和第3個數,將小數放前,大數放後,如此繼續, 直至比較最後兩個數,將小數放前,大數放後。 至此第一趟結束,將最大的數放到了最後。
  * 依次執行以上步驟a.leng-1次,排序完成。
  * 
  * @param a
  */
 public static void bubble(int[] a) {
  // {1, 5, 5, 3, 4, 3,2}
  for (int i = 1; i < a.length; i++) {
   for (int j = 0; j < a.length - i; j++) {
    if (a[j + 1] < a[j]) {
     int temp = a[j + 1];
     a[j + 1] = a[j];
     a[j] = temp;
    }
   }
  }
 }

2、  快速排序:

①   思想:冒泡排序一次只能消除一個逆序,爲了能一次消除多個逆序,採用快速排序。以一個關鍵字爲軸,從左從右依次與其進行對比,然後交換,第一趟結束後,可以把序列分爲兩個子序列,然後再分段進行快速排序,達到高效。

②   時間複雜度:平均T(n) = O(n㏒n),最壞O(n)。

③   空間複雜度:S(n) = O(㏒n)。

④   穩定性:不穩定排序。{3, 2, 2}

⑤   程序:

 /**
  * 快速排序:
  * 一趟快速排序的算法是: 
  * 1)設置兩個變量l、h,排序開始的時候:l=0,h=N-1;
  * 2)以第一個數組元素作爲關鍵數據,賦值給key,即key=A[0];
  * 3)從j開始向前搜索,即由後開始向前搜索,找到第一個小於key的值A[j],將A[j]和A[i]互換,然後h--;
  * 4)從i開始向後搜索,即由前開始向後搜索,找到第一個大於key的A[i],將A[i]和A[j]互換,然後l++;
  *  5)重複第3、4步,直到l==h
  * 
  * @param a
  */
 public static void quick(int[] a, int l, int h) {
  int low = l;
  int high = h;
  int key = a[low];
  while (low < high) {
   //從後往前找
   while (low < high && key < a[high]) {
    high--;
   }
   if (low < high) {
    int temp = a[high];
    a[high] = a[low];
    a[low] = temp;
    low++;
   }
   //從前往後找
   while (low < high && key > a[low]) {
    low++;
   }
   if (low < high) {
    int temp = a[high];
    a[high] = a[low];
    a[low] = temp;
    high--;
   }
  }
  if (low > l) {
   quick(a, l, low-1);
  }
  if (high < h) {
   quick(a, high+1, h);
  }
 }

選擇類排序:

(一)   思想:每一趟在n – i + 1 ( i = 1,2, … , n - 1)個記錄中選取關鍵字最小的記錄作爲有序序列中的第i個記錄。

(二)   分類:

1、  簡單選擇排序:

①   思想:第一趟時,從第一個記錄開始,通過n – 1次關鍵字的比較,從n個記錄中選出關鍵字最小的記錄,並和第一個記錄進行交換。第二趟從第二個記錄開始,選擇最小的和第二個記錄交換。以此類推,直至全部排序完畢。

②   時間複雜度:T(n) = O(n)。

③   空間複雜度:S(n) = O(1)。

④   穩定性:不穩定排序,{3, 3, 2}。

⑤   程序:

 /**
  * 選擇排序:
  * 在第一趟遍歷N個數據,找出其中最小的數值與第一個元素交換,
  * 第二趟遍歷剩下的N-1個數據,找出其中最小的數值與第二個元素交換......
  * 第N-1趟遍歷剩下的2個數據,找出其中最小的數值與第N-1個元素交換,
  * 至此選擇排序完成。
  * @param a
  */
 public static void selectSort(int[] a) {
  //{ 1, 5, 5, 3, 4, 3, 2 };
  for(int i=1; i<a.length; i++) {
   int flag = i-1;
   for(int j=i; j<a.length; j++) {
    if(a[flag] > a[j]) {
     flag = j;
    }
   }
   if(flag != i-1) {
    int temp = a[flag];
    a[flag] = a[i-1];
    a[i-1] = temp;
   }
   toString(a);
  }
 }

3、  堆排序:

①   思想:把待排序記錄的關鍵字存放在數組r[1…n]中,將r看成是一刻完全二叉樹的順序表示,每個節點表示一個記錄,第一個記錄r[1]作爲二叉樹的根,一下個記錄r[2…n]依次逐層從左到右順序排列,任意節點r[i]的左孩子是r[2i],右孩子是r[2i+1],雙親是r[i/2向下取整]。然後對這棵完全二叉樹進行調整建堆。

②   時間複雜度:T(n) = O(n㏒n)。

③   空間複雜度:S(n) = O(1)。

④   穩定性:不穩定排序。{5, 5, 3}

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