十大經典排序算法最強總結(含JAVA代碼實現)

2021-02-13 Java專欄

第一時間閱讀精彩文章!

2、☞ 《Java面試手冊》.PDF    點擊查看

轉載自https://www.cnblogs.com/guoyaohua/p/8600214.html#4264874

最近幾天在研究排序算法,看了很多博客,發現網上有的文章中對排序算法解釋的並不是很透徹,而且有很多代碼都是錯誤的,例如有的文章中在桶排序算法中對每個桶進行排序直接使用了 Collection.sort() 函數,這樣雖然能達到效果,但對於算法研究來講是不可以的。所以我根據這幾天看的文章,整理了一個較為完整的排序算法總結,本文中的所有算法均有JAVA實現,經本人調試無誤後才發出,如有錯誤,請各位前輩指出。

0、排序算法說明0.1 排序的定義

對一序列對象根據某個關鍵字進行排序。

0.2 術語說明

穩定:如果a原本在b前面,而a=b,排序之後a仍然在b的前面;

不穩定:如果a原本在b的前面,而a=b,排序之後a可能會出現在b的後面;

內排序:所有排序操作都在內存中完成;

外排序:由於數據太大,因此把數據放在磁碟中,而排序通過磁碟和內存的數據傳輸才能進行;

時間複雜度: 一個算法執行所耗費的時間。

空間複雜度:運行完一個程序所需內存的大小。

0.3 算法總結

圖片名詞解釋:

n: 數據規模

k: 「桶」的個數

In-place: 佔用常數內存,不佔用額外內存

Out-place: 佔用額外內存

0.5 算法分類比較和非比較的區別

常見的快速排序、歸併排序、堆排序、冒泡排序等屬於比較排序在排序的最終結果裡,元素之間的次序依賴於它們之間的比較。每個數都必須和其他數進行比較,才能確定自己的位置。
冒泡排序之類的排序中,問題規模為n,又因為需要比較n次,所以平均時間複雜度為O(n²)。在歸併排序、快速排序之類的排序中,問題規模通過分治法消減為logN次,所以時間複雜度平均O(nlogn)
比較排序的優勢是,適用於各種規模的數據,也不在乎數據的分布,都能進行排序。可以說,比較排序適用於一切需要排序的情況。

計數排序、基數排序、桶排序則屬於非比較排序。非比較排序是通過確定每個元素之前,應該有多少個元素來排序。針對數組arr,計算arr[i]之前有多少個元素,則唯一確定了arr[i]在排序後數組中的位置。
非比較排序只要確定每個元素之前的已有的元素個數即可,所有一次遍歷即可解決。算法時間複雜度O(n)
非比較排序時間複雜度底,但由於非比較排序需要佔用空間來確定唯一位置。所以對數據規模和數據分布有一定的要求

1、冒泡排序(Bubble Sort)

冒泡排序是一種簡單的排序算法。它重複地走訪過要排序的數列,一次比較兩個元素,如果它們的順序錯誤就把它們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因為越小的元素會經由交換慢慢浮到數列的頂端。

1.1 算法描述

1.2 動圖演示

1.3 代碼實現

/**
     * 冒泡排序
     *
     * @param array
     * @return
     */
public static int[] bubbleSort(int[] array) {
  if (array.length == 0)
    return array;
  for (int i = 0; i < array.length; i++)
    for (int j = 0; j < array.length - 1 - i; j++)
      if (array[j + 1] < array[j]) {
        int temp = array[j + 1];
        array[j + 1] = array[j];
        array[j] = temp;
      }
  return array;
}

1.4 算法分析

最佳情況:T(n) = O(n) 最差情況:T(n) = O(n2) 平均情況:T(n) = O(n2)

2、選擇排序(Selection Sort)

表現最穩定的排序算法之一,因為無論什麼數據進去都是 O(n2) 的時間複雜度,所以用到它的時候,數據規模越小越好。唯一的好處可能就是不佔用額外的內存空間了吧。理論上講,選擇排序可能也是平時排序一般人想到的最多的排序方法了吧。

選擇排序(Selection-sort) 是一種簡單直觀的排序算法。它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。

2.1 算法描述

n 個記錄的直接選擇排序可經過n-1趟直接選擇排序得到有序結果。具體算法描述如下:

2.2 動圖演示

2.3 代碼實現

/**
     * 選擇排序
     * @param array
     * @return
     */
public static int[] selectionSort(int[] array) {
  if (array.length == 0)
    return array;
  for (int i = 0; i < array.length; i++) {
    int minIndex = i;
    for (int j = i; j < array.length; j++) {
      if (array[j] < array[minIndex]) //找到最小的數
        minIndex = j; //將最小數的索引保存
    }
    int temp = array[minIndex];
    array[minIndex] = array[i];
    array[i] = temp;
  }
  return array;
}

2.4 算法分析

最佳情況:T(n) = O(n2) 最差情況:T(n) = O(n2) 平均情況:T(n) = O(n2)

3、插入排序(Insertion Sort)

插入排序(Insertion-Sort)的算法描述是一種簡單直觀的排序算法。它的工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。插入排序在實現上,通常採用 in-place 排序(即只需用到O(1)的額外空間的排序),因而在從後向前掃描過程中,需要反覆把已排序元素逐步向後挪位,為最新元素提供插入空間。

3.1 算法描述

一般來說,插入排序都採用 in-place 在數組上實現。具體算法描述如下:

從第一個元素開始,該元素可以認為已經被排序;

取出下一個元素,在已經排序的元素序列中從後向前掃描;

如果該元素(已排序)大於新元素,將該元素移到下一位置;

重複步驟3,直到找到已排序的元素小於或者等於新元素的位置;

將新元素插入到該位置後;

重複步驟2~5。

3.2 動圖演示

3.2 代碼實現

/**
     * 插入排序
     * @param array
     * @return
     */
public static int[] insertionSort(int[] array) {
  if (array.length == 0)
    return array;
  int current;
  for (int i = 0; i < array.length - 1; i++) {
    current = array[i + 1];
    int preIndex = i;
    while (preIndex >= 0 && current < array[preIndex]) {
      array[preIndex + 1] = array[preIndex];
      preIndex--;
    }
    array[preIndex + 1] = current;
  }
  return array;
}

3.4 算法分析

最佳情況:T(n) = O(n) 最壞情況:T(n) = O(n2) 平均情況:T(n) = O(n2)

4、希爾排序(Shell Sort)

希爾排序是希爾(Donald Shell)於1959年提出的一種排序算法。希爾排序也是一種插入排序,它是簡單插入排序經過改進之後的一個更高效的版本,也稱為縮小增量排序,同時該算法是衝破 O(n2)的第一批算法之一。它與插入排序的不同之處在於,它會優先比較距離較遠的元素。希爾排序又叫縮小增量排序。

希爾排序是把記錄按下表的一定增量分組,對每組使用直接插入排序算法排序;隨著增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便終止。

4.1 算法描述

我們來看下希爾排序的基本步驟,在此我們選擇增量 gap=length/2,縮小增量繼續以 gap = gap/2 的方式,這種增量選擇我們可以用一個序列來表示,{n/2,(n/2)/2…1},稱為增量序列。希爾排序的增量序列的選擇與證明是個數學難題,我們選擇的這個增量序列是比較常用的,也是希爾建議的增量,稱為希爾增量,但其實這個增量序列不是最優的。此處我們做示例使用希爾增量。

先將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序,具體算法描述:

4.2 過程演示4.3 代碼實現

/**
     * 希爾排序
     *
     * @param array
     * @return
     */
public static int[] ShellSort(int[] array) {
  int len = array.length;
  int temp, gap = len / 2;
  while (gap > 0) {
    for (int i = gap; i < len; i++) {
      temp = array[i];
      int preIndex = i - gap;
      while (preIndex >= 0 && array[preIndex] > temp) {
        array[preIndex + gap] = array[preIndex];
        preIndex -= gap;
      }
      array[preIndex + gap] = temp;
    }
    gap /= 2;
  }
  return array;
}

4.4 算法分析

最佳情況:T(n) = O(nlog2 n) 最壞情況:T(n) = O(nlog2 n) 平均情況:T(n) =O(nlog2n) 

5、歸併排序(Merge Sort)

和選擇排序一樣,歸併排序的性能不受輸入數據的影響,但表現比選擇排序好的多,因為始終都是 O(n log n)的時間複雜度。代價是需要額外的內存空間。

歸併排序是建立在歸併操作上的一種有效的排序算法。該算法是採用分治法(Divide and Conquer)的一個非常典型的應用。歸併排序是一種穩定的排序方法。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱為2-路歸併。

5.1 算法描述5.2 動圖演示

5.3 代碼實現

/**
     * 歸併排序
     *
     * @param array
     * @return
     */
public static int[] MergeSort(int[] array) {
  if (array.length < 2) return array;
  int mid = array.length / 2;
  int[] left = Arrays.copyOfRange(array, 0, mid);
  int[] right = Arrays.copyOfRange(array, mid, array.length);
  return merge(MergeSort(left), MergeSort(right));
}
/**
     * 歸併排序——將兩段排序好的數組結合成一個排序數組
     *
     * @param left
     * @param right
     * @return
     */
public static int[] merge(int[] left, int[] right) {
  int[] result = new int[left.length + right.length];
  for (int index = 0, i = 0, j = 0; index < result.length; index++) {
    if (i >= left.length)
      result[index] = right[j++];
    else if (j >= right.length)
      result[index] = left[i++];
    else if (left[i] > right[j])
      result[index] = right[j++];
    else
      result[index] = left[i++];
  }
  return result;
}

5. 4 算法分析

最佳情況:T(n) = O(n) 最差情況:T(n) = O(nlogn) 平均情況:T(n) = O(nlogn)

6、快速排序(Quick Sort)

快速排序的基本思想:通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。

6.1 算法描述

快速排序使用分治法來把一個串(list)分為兩個子串(sub-lists)。具體算法描述如下:

6.2 動圖演示6.3 代碼實現

  /**
     * 快速排序方法
     */
public static int[] QuickSort(int[] array, int start, int end) {
  if (array.length < 1 || start < 0 || end >= array.length || start > end) return null;
  int smallIndex = partition(array, start, end);
  if (smallIndex > start)
    QuickSort(array, start, smallIndex - 1);
  if (smallIndex < end)
    QuickSort(array, smallIndex + 1, end);
  return array;
}
/**
     * 快速排序算法——partition
     */
public static int partition(int[] array, int start, int end) {
  int pivot = (int) (start + Math.random() * (end - start + 1));
  int smallIndex = start - 1;
  swap(array, pivot, end);
  for (int i = start; i <= end; i++)
    if (array[i] <= array[end]) {
      smallIndex++;
      if (i > smallIndex)
        swap(array, i, smallIndex);
    }
  return smallIndex;
}

/**
     * 交換數組內兩個元素
     */
public static void swap(int[] array, int i, int j) {
  int temp = array[i];
  array[i] = array[j];
  array[j] = temp;
}

6.4 算法分析

最佳情況:T(n) = O(nlogn) 最差情況:T(n) = O(n2) 平均情況:T(n) = O(nlogn) 

7、堆排序(Heap Sort)

堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。堆積是一個近似完全二叉樹的結構,並同時滿足堆積的性質:即子結點的鍵值或索引總是小於(或者大於)它的父節點。

7.1 算法描述

將初始待排序關鍵字序列(R1,R2….Rn)構建成大頂堆,此堆為初始的無序區;

將堆頂元素R[1]與最後一個元素R[n]交換,此時得到新的無序區(R1,R2,……Rn-1)和新的有序區(Rn),且滿足R[1,2…n-1]<=R[n];

由於交換後新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,……Rn-1)調整為新堆,然後再次將R[1]與無序區最後一個元素交換,得到新的無序區(R1,R2….Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數為n-1,則整個排序過程完成。

7.2 動圖演示

7.3 代碼實現

//聲明全局變量,用於記錄數組array的長度;
static int len;
/**
     * 堆排序算法
     *
     * @param array
     * @return
     */
public static int[] HeapSort(int[] array) {
  len = array.length;
  if (len < 1) return array;
  //1.構建一個最大堆
  buildMaxHeap(array);
  //2.循環將堆首位(最大值)與末位交換,然後在重新調整最大堆
  while (len > 0) {
    swap(array, 0, len - 1);
    len--;
    adjustHeap(array, 0);
  }
  return array;
}
/**
     * 建立最大堆
     *
     * @param array
     */
public static void buildMaxHeap(int[] array) {
  //從最後一個非葉子節點開始向上構造最大堆
  for (int i = (len/2 - 1); i >= 0; i--) { //感謝 @讓我發會呆 網友的提醒,此處應該為 i = (len/2 - 1) 
    adjustHeap(array, i);
  }
}
/**
     * 調整使之成為最大堆
     *
     * @param array
     * @param i
     */
public static void adjustHeap(int[] array, int i) {
  int maxIndex = i;
  //如果有左子樹,且左子樹大於父節點,則將最大指針指向左子樹
  if (i * 2 < len && array[i * 2] > array[maxIndex])
    maxIndex = i * 2;
  //如果有右子樹,且右子樹大於父節點,則將最大指針指向右子樹
  if (i * 2 + 1 < len && array[i * 2 + 1] > array[maxIndex])
    maxIndex = i * 2 + 1;
  //如果父節點不是最大值,則將父節點與最大值交換,並且遞歸調整與父節點交換的位置。
  if (maxIndex != i) {
    swap(array, maxIndex, i);
    adjustHeap(array, maxIndex);
  }
}

7.4 算法分析

最佳情況:T(n) = O(nlogn) 最差情況:T(n) = O(nlogn) 平均情況:T(n) = O(nlogn)

8、計數排序(Counting Sort)

計數排序的核心在於將輸入的數據值轉化為鍵存儲在額外開闢的數組空間中。作為一種線性時間複雜度的排序,計數排序要求輸入的數據必須是有確定範圍的整數。

計數排序(Counting sort)是一種穩定的排序算法。計數排序使用一個額外的數組C,其中第i個元素是待排序數組A中值等於i的元素的個數。然後根據數組C來將A中的元素排到正確的位置。它只能對整數進行排序。

8.1 算法描述

找出待排序的數組中最大和最小的元素;

統計數組中每個值為i的元素出現的次數,存入數組C的第i項;

對所有的計數累加(從C中的第一個元素開始,每一項和前一項相加);

反向填充目標數組:將每個元素i放在新數組的第C(i)項,每放一個元素就將C(i)減去1。

8.2 動圖演示8.3 代碼實現

/**
     * 計數排序
     *
     * @param array
     * @return
     */
public static int[] CountingSort(int[] array) {
  if (array.length == 0) return array;
  int bias, min = array[0], max = array[0];
  for (int i = 1; i < array.length; i++) {
    if (array[i] > max)
      max = array[i];
    if (array[i] < min)
      min = array[i];
  }
  bias = 0 - min;
  int[] bucket = new int[max - min + 1];
  Arrays.fill(bucket, 0);
  for (int i = 0; i < array.length; i++) {
    bucket[array[i] + bias]++;
  }
  int index = 0, i = 0;
  while (index < array.length) {
    if (bucket[i] != 0) {
      array[index] = i - bias;
      bucket[i]--;
      index++;
    } else
      i++;
  }
  return array;
}

8.4 算法分析

當輸入的元素是 n 個 0 到 k 之間的整數時,它的運行時間是 O(n + k)。計數排序不是比較排序,排序的速度快於任何比較排序算法。由於用來計數的數組C的長度取決於待排序數組中數據的範圍(等於待排序數組的最大值與最小值的差加上1),這使得計數排序對於數據範圍很大的數組,需要大量時間和內存。

最佳情況:T(n) = O(n+k) 最差情況:T(n) = O(n+k) 平均情況:T(n) = O(n+k)

9、桶排序(Bucket Sort)

桶排序是計數排序的升級版。它利用了函數的映射關係,高效與否的關鍵就在於這個映射函數的確定。

桶排序 (Bucket sort)的工作的原理:假設輸入數據服從均勻分布,將數據分到有限數量的桶裡,每個桶再分別排序(有可能再使用別的排序算法或是以遞歸方式繼續使用桶排序進行排

9.1 算法描述

人為設置一個BucketSize,作為每個桶所能放置多少個不同數值(例如當BucketSize==5時,該桶可以存放{1,2,3,4,5}這幾種數字,但是容量不限,即可以存放100個3);

遍歷輸入數據,並且把數據一個一個放到對應的桶裡去;

對每個不是空的桶進行排序,可以使用其它排序方法,也可以遞歸使用桶排序;

從不是空的桶裡把排好序的數據拼接起來。

注意,如果遞歸使用桶排序為各個桶排序,則當桶數量為1時要手動減小 BucketSize 增加下一循環桶的數量,否則會陷入死循環,導致內存溢出。

9.2 圖片演示9.3 代碼實現

/**
     * 桶排序
     * 
     * @param array
     * @param bucketSize
     * @return
     */
public static ArrayList<Integer> BucketSort(ArrayList<Integer> array, int bucketSize) {
  if (array == null || array.size() < 2)
    return array;
  int max = array.get(0), min = array.get(0);
  // 找到最大值最小值
  for (int i = 0; i < array.size(); i++) {
    if (array.get(i) > max)
      max = array.get(i);
    if (array.get(i) < min)
      min = array.get(i);
  }
  int bucketCount = (max - min) / bucketSize + 1;
  ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketCount);
  ArrayList<Integer> resultArr = new ArrayList<>();
  for (int i = 0; i < bucketCount; i++) {
    bucketArr.add(new ArrayList<Integer>());
  }
  for (int i = 0; i < array.size(); i++) {
    bucketArr.get((array.get(i) - min) / bucketSize).add(array.get(i));
  }
  for (int i = 0; i < bucketCount; i++) {
    if (bucketSize == 1) { // 如果帶排序數組中有重複數字時  感謝 @見風任然是風 朋友指出錯誤
      for (int j = 0; j < bucketArr.get(i).size(); j++)
        resultArr.add(bucketArr.get(i).get(j));
    } else {
      if (bucketCount == 1)
        bucketSize--;
      ArrayList<Integer> temp = BucketSort(bucketArr.get(i), bucketSize);
      for (int j = 0; j < temp.size(); j++)
        resultArr.add(temp.get(j));
    }
  }
  return resultArr;
}

9.4 算法分析

桶排序最好情況下使用線性時間 O(n),桶排序的時間複雜度,取決與對各個桶之間數據進行排序的時間複雜度,因為其它部分的時間複雜度都為 O(n)。很顯然,桶劃分的越小,各個桶之間的數據越少,排序所用的時間也會越少。但相應的空間消耗就會增大。

最佳情況:T(n) = O(n+k) 最差情況:T(n) = O(n+k) 平均情況:T(n) = O(n2)  

10、基數排序(Radix Sort)

基數排序也是非比較的排序算法,對每一位進行排序,從最低位開始排序,複雜度為O(kn),為數組長度,k為數組中的數的最大的位數;

基數排序是按照低位先排序,然後收集;再按照高位排序,然後再收集;依次類推,直到最高位。有時候有些屬性是有優先級順序的,先按低優先級排序,再按高優先級排序。最後的次序就是高優先級高的在前,高優先級相同的低優先級高的在前。基數排序基於分別排序,分別收集,所以是穩定的。

10.1 算法描述10.2 動圖演示10.3 代碼實現

/**
     * 基數排序
     * @param array
     * @return
     */
public static int[] RadixSort(int[] array) {
  if (array == null || array.length < 2)
    return array;
  // 1.先算出最大數的位數;
  int max = array[0];
  for (int i = 1; i < array.length; i++) {
    max = Math.max(max, array[i]);
  }
  int maxDigit = 0;
  while (max != 0) {
    max /= 10;
    maxDigit++;
  }
  int mod = 10, div = 1;
  ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>();
  for (int i = 0; i < 10; i++)
    bucketList.add(new ArrayList<Integer>());
  for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) {
    for (int j = 0; j < array.length; j++) {
      int num = (array[j] % mod) / div;
      bucketList.get(num).add(array[j]);
    }
    int index = 0;
    for (int j = 0; j < bucketList.size(); j++) {
      for (int k = 0; k < bucketList.get(j).size(); k++)
        array[index++] = bucketList.get(j).get(k);
      bucketList.get(j).clear();
    }
  }
  return array;
}

10.4 算法分析

最佳情況:T(n) = O(n * k) 最差情況:T(n) = O(n * k) 平均情況:T(n) = O(n * k)

基數排序有兩種方法:

MSD 從高位開始進行排序 LSD 從低位開始進行排序

基數排序 vs 計數排序 vs 桶排序

這三種排序算法都利用了桶的概念,但對桶的使用方法上有明顯差異:

基數排序:根據鍵值的每位數字來分配桶

計數排序:每個桶只存儲單一鍵值

桶排序:每個桶存儲一定範圍的數值

以上,便是今天的分享,希望大家喜歡,覺得內容不錯的,歡迎點擊「在看」支持,謝謝各位

獲取方式:

1、公眾號後臺回復「手冊」

2、掃描下方二維碼,回復「手冊」

相關焦點

  • Java實現冒泡排序算法
    學習方法推薦:#學習方法1.從基礎開始,系統化學習2.多動手,每一種數據結構與算法,都自己用代碼實現出來3.思路更重要:理解實現思想,不要背代碼4.與日常開發結合,對應應用場景學習內容推薦:數據結構與算法內容比較多,我們本著實用原則,學習經典的、常用的數據結構、與常用算法#學習內容:1.數據結構的定義2.算法的定義3.複雜度分析4
  • JS家的排序算法 十大經典算法排序總結
    它是一本很好的針對前端開發者們的入門算法書籍,可是,它有一個很大的缺陷,就是裡面有很多明顯的小錯誤,明顯到就連我這種半路出家的程序猿都能一眼看出來。還有一個問題是,很多重要的算法和數據結構知識並沒有在這本書裡被提到。這些問題對於作為一個晚期強迫症患者的我來說簡直不能忍。於是乎,一言不合我就決定自己找資料總結算法。那麼,我就從算法領域裡最基礎的知識點——排序算法總結起好了。
  • 十大經典排序算法最強總結
    排序算法屬於經典基礎算法基本功,筆試面試基本都會涉及和考察的,有原題也有變化,不過基礎的幾大排序算法還是得儘可能熟悉
  • 經典排序算法三 選擇排序(JAVA實現)
    選擇排序原理:每一趟從待排序的記錄中選出最小的元素,順序放在已排好序的序列最後,直到全部記錄排序完畢。也就是:每一趟在n-i+1(i=1,2,…n-1)個記錄中選取關鍵字最小的記錄作為有序序列中第i個記錄。基於此思想的算法主要有簡單選擇排序、樹型選擇排序和堆排序。
  • 十大經典排序算法(動圖+代碼)
    下個月又將舉行信息奧賽了,一起來複習十大經典排序算法。
  • SelectionSort 選擇排序算法詳解(java 實現)
    選擇排序選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。選擇排序的主要優點與數據移動有關。
  • 經典排序算法一 冒泡排序(JAVA實現)
    冒泡排序原理:相鄰的兩個元素進行比較,將值大的元素移動到右端。冒泡排序實現思路:遍歷要排序的元素,依次比較相鄰的兩個元素,值大的移動到右端,則第二次就可以忽略第一次遍歷放在最右端的元素,依次類推直到遍歷到n-1次只剩下2個元素進行比較,冒泡排序結束。
  • 十大經典排序算法之希爾排序算法
    這就是希爾排序的思想。代碼實現#!random.randint(min_number, max_number) for _ in range(num)]    print(array)    shell_sort_original(array)    print(array)乍一看,這個程序一共有四層循環,是不是覺得這個程序怎麼可能是插入排序的優化算法呢
  • 排序算法---基數排序,動圖詳解,Java實現!
    「代碼實現:」定義桶(二維數組):int[][] bucket = new int[10][arr.length];除了桶這個需要額外空間之外最後arr數組就會按照升序排序結束。在此只展示代碼不同的地方,其餘地方完全一樣。//算法:取出十位的數字int digitOfElement = arr[j] / 10 % 10;
  • 十大經典排序算法大梳理 (動圖+代碼)
    歸併排序是建立在歸併操作上的一種有效的排序算法。希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。計數排序基於一個假設,待排序數列的所有數均為整數,且出現在(0,k)的區間之內。如果 k(待排數組的最大值) 過大則會引起較大的空間複雜度,一般是用來排序 0 到 100 之間的數字的最好的算法,但是它不適合按字母順序排序人名。計數排序不是比較排序,排序的速度快於任何比較排序算法。
  • Java 快速排序算法
    簡介上一章我們學習了 [Java 希爾排序算法],這一章,我們來學習快速排序算法
  • 十大經典排序算法(動態演示+代碼)!乾貨收藏
    堆排序(Heapsort)是指利用堆這種數據結構所設計的一種排序算法。歸併排序是建立在歸併操作上的一種有效的排序算法。希爾排序,也稱遞減增量排序算法,是插入排序的一種更高效的改進版本。但希爾排序是非穩定排序算法。先將整個待排序的記錄序列分割成為若干子序列分別進行直接插入排序.
  • 程式設計師必知必會的十大排序算法
    緒論身為程式設計師,十大排序是所有合格程式設計師所必備和掌握的,並且熱門的算法比如快排、歸併排序還可能問得比較細緻,對算法性能和複雜度的掌握都有要求。本文將帶你捋一捋常見的十大排序算法,讓你輕輕鬆鬆掌握!首先對於排序來說,大多數人對排序的概念停留在冒泡排序或者JDK中的Arrays.sort(),手寫各種排序對很多人來說都是一種奢望,更別說十大排序算法了。對於排序的分類,可以根據不同的維度比如複雜度、內外部、比較非比較等維度來分類。
  • 輕鬆搞定Java冒泡排序算法以及算法優化
    作為Java程式設計師,簡單的算法,必須要掌握的。尤其初級開發人員在面試過程或者筆試都會有相應算法題,今天我們講解冒泡排序算法是如何實現的以及優化方法。何為冒泡排序冒泡排序的基本思路:通過對待排序系列從前向後,依次比較相鄰元素的值,若發現逆序就交換,意思就是使較大的元素從前向後移,好比水低下的氣泡一樣逐漸向上冒泡,一個道理的。冒泡排序優缺點優點:比較簡單、空間複雜度較低、是穩定的一種排序。
  • 八十七、Python|十大排序算法系列(上篇)
    辣雞的我決定繼續更新Python教程,今天就開始了八十七、Python | 十大排序算法系列(上篇)。還有不到區區的十三篇,我快完成了。如果把基礎的數據結構與算法都自己親自實現一遍,那麼你已經比 90% 的 Python 程式設計師更優秀了。
  • Java中常見的排序算法有哪些?---冒泡排序
    排序相關的的基本概念排序: 將一組雜亂無章的數據按一定的規律順次排列起來。數據表( data list): 它是待排序數據對象的有限集合。排序碼(key):通常數據對象有多個屬性域,即多個數據成員組成,其中有一個屬性域可用來區分對象,作為排序依據。該域即為排序碼。
  • 《數據結構與算法》十大經典排序算法動圖演示(2019最新Python代碼)
    Python 代碼實現def bubbleSort(arr):    for i in range(1, len(arr)):        for j in range(0, len(arr)-i):            if arr[j] > arr[j+1]:                arr[j], arr
  • 一文圖解 Java 源碼的插入排序算法
    資料地址:https://en.wikipedia.org/wiki/External_sorting上一篇《程序兵法:Java String 源碼的排序算法(一)》,講到了 java.lang.Comparable 接口。那麼接口是一個抽象類型,是抽象方法(compareTo)的集合,用 interface 來聲明。
  • 排序算法總結(1):冒泡排序
    冒泡排序是一種交換排序。什麼是交換排序呢?交換排序:兩兩比較待排序的關鍵字,並交換不滿足次序要求的那對數,直到整個表都滿足次序要求為止。算法思想它重複地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。
  • 排序算法:選擇排序
    在日常開發中經常會遇到一類問題,就是對一個集合的數據進行排序掌握一些排序算法,對於日常開發是非常有幫助的今天介紹一下選擇排序法01算法邏輯,選擇排序每次交換所使用的臨時變量為 i,j,最大數據位置,每次循環總大小,tmp由臨時變量數可以得出,選擇排序的空間複雜度為04java代碼實現public int[] sortBySelect(int[] data) {int location