日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【数据结构-排序】1. 图解插入排序三种实现(插入排序/折半排序/希尔排序)

發布時間:2025/3/20 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【数据结构-排序】1. 图解插入排序三种实现(插入排序/折半排序/希尔排序) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

直接插入排序(插入排序)

排序思想

  • 對于一個數組 A[0,n] 的排序問題,假設認為數組在 A[0,n-1] 排序的問題已經解決了。
  • 考慮 A[n] 的值,從右向左掃描有序數組 A[0,n-1] ,直到第一個小于等于 A[n] 的元素,將 A[n] 插在這個元素的后面。

插入排序運用時需要注意的

直接插入排序對于 最壞的情況(嚴格遞減/遞增的數組),需要比較和移位的次數為 n(n-1)/2;

對于 最好的情況(嚴格遞增/遞減的數組),需要比較的次數是 n-1 ,需要移位的次數是 0 。

直接插入排序適用于 順序存儲鏈式存儲結構 的線性表。注意,為鏈式存儲時,可以從前往后查找指定元素的位置。一般來說,當 數據規模較小 的情況下,可以考慮使用直接插入排序

插入排序算法分析

直接插入排序的時間復雜度是 O(n^2),空間復雜度是 O(1),同時也是 穩定排序

穩定排序:待排序的記錄序列中可能存在兩個或兩個以上關鍵字相等的記錄。排序前的序列中Ri領先于Rj(即i<j).若在排序后的序列中Ri仍然領先于Rj,則稱所用的方法是穩定的。

比如int數組[1,1,1,6,4]中a[0],a[1],a[2]的值相等,在排序時不改變其序列,則稱所用的方法是穩定的。

代碼實現

class Solution{ public:void insertSortion(vector<int> &nums) {if(nums.size() < 2) return;for(int i = 1; i < nums.size(); i++) {int num = nums[i];// 防止插入的數是最小的 bool flag = false;// for循環中,若插入值是最小的,沒有給最小的值安排位置 for(int j = i - 1; j > -1; j--) {if(nums[j] > num) {nums[j+1] = nums[j];} else {nums[j+1] = num;flag = true;break;}}if(!flag) {nums[0] = num; }}return;} };

加工后執行的結果

折半插入排序(插入排序)

排序思想:折半插入排序的改進版

  • 有一組數列待排序,排序區間為 Array[0, n-1] 。將數列分為有序數列和無序數列,第一次排序時默認 Array[0] 為有序數列,Array[1, n-1] 為無序數列。有序數列分區的第一個元素位置為 low ,最后一個元素的位置為 high。
  • 設 Array[0, i-1] 為有序數列,待插入數據為 Array[i]。由于 Array[0, i-1] 有序,使用對有序數列的查找,最好的方法時時間復雜度為 O(logn) 的折半查找,通過折半查找找到插入位置(即 low > high 時),將該位置及之后的數據分別往后挪一位
  • 折半插入排序運用時需要注意的條件和直接插入排序時需注意的條件一樣

    折半插入排序對于 最壞的情況(嚴格遞減/遞增的數組),需要比較和移位的次數為 n(n-1)/2 ;

    對于 最好的情況(嚴格遞增/遞減的數組),需要比較的次數是 n-1 ,需要移位的次數是 0。

    但相比直接插入排序,折半插入排序在 查找位置的時候得到優化(O(n)→ O(logn))

    折半排序算法分析

    折半插入排序的時間復雜度是 O(n^2),空間復雜度是O(1),同時也是 穩定排序

    代碼實現

    #include <stdio.h> #include <vector> using namespace std; class Solution{ public:void binaryInsertionSort(vector<int> &nums) {if(nums.size() < 2) return;for(int i = 1; i < nums.size(); i++) {int low = 0;int high = i;int num = nums[i];while(low <= high) {int mid = (low + high) / 2;if(nums[mid] > num) {high = mid - 1;} else {low = mid + 1;}}int j;for(j = i - 1; j > high; j--) {nums[j+1] = nums[j];}nums[j+1] = num; }return; } };

    加工后執行的結果

    希爾排序(插入排序)

    排序思想:通過粗調的方式減少了直接插入排序的工作量

    對于 Array[0,n-1] 這個數列有 n 個待排序的數字,取一個小于 n 的整數 step (step被稱為步長)將待排序元素分成若干個組子序列,所有距離為 step 的倍數的記錄放在同一個組中;然后,對各組內的元素進行直接插入排序。 這一趟排序完成之后,每一個組的元素都是有序的。然后減小 step 的值,并重復執行上述的分組和排序。重復這樣的操作,當 step=1 時,整個數列就是有序的。

    希爾排序

    希爾排序的時間復雜度與增量(即,步長 step )的選取有關。例如,當增量 step 為1時,希爾排序退化成了直接插入排序,此時的時間復雜度為 O(n2)

    遇到極端情況,比如 step=4 和 step=2 時,數組序列不變,進入 step=1 時,就是直接插入排序了,相比正常的直接插入排序,還多加了幾次 step=4 和 step=2 的判斷

    希爾排序僅適用于線性表為順序存儲的情況。

    希爾排序算法分析

    希爾插入排序的時間復雜度是 O(n^2),空間復雜度是 O(1) ,但希爾排序是 不穩定排序

    代碼實現

    class Solution{ public:void ShellSort(vector<int> &nums) {int size = nums.size();int count = 0;for(int step = size / 2; step > 0; step /= 2) {for(int i = 0; i < step; i++) {insertSort(nums, size, i, step);}}} private:void insertSort(vector<int> &nums, int size, int i, int step){for(int j = i + step; j < size; j+=step) {if(nums[j] < nums[j-step]) {int num = nums[j];int k = j - step;while(k >= 0 && nums[k] > num) {nums[k+step] = nums[k];k -= step;}nums[k+step] = num;}}return;} };

    加工后執行的結果

    完整測試代碼

    直接插入排序測試代碼

    #include <stdio.h> #include <vector> using namespace std; class Solution{ public:void insertSortion(vector<int> &nums) {if(nums.size() < 2) return;printf("第0輪:");for(int i = 0; i < nums.size(); i++) {printf("%d",nums[i]);if(i!=nums.size()-1) printf(",");}printf("\n");for(int i = 1; i < nums.size(); i++) {int num = nums[i];// 防止插入的數是最小的 bool flag = false;// for循環中,若插入值是最小的,沒有給最小的值安排位置 for(int j = i - 1; j > -1; j--) {if(nums[j] > num) {nums[j+1] = nums[j];} else {nums[j+1] = num;flag = true;break;}}if(!flag) {nums[0] = num; }// 查看 printf("第%d輪:",i);for(int i = 0; i < nums.size(); i++) {printf("%d",nums[i]);if(i!=nums.size()-1) printf(",");}printf("\n");}return;} };int main() {vector<int> v;v.push_back(23);v.push_back(76);v.push_back(34);v.push_back(89);v.push_back(90);v.push_back(34);v.push_back(56);v.push_back(18);Solution solution;solution.insertSortion(v);return 0; }

    折半插入排序測試代碼

    #include <stdio.h> #include <vector> using namespace std; class Solution{ public:void binaryInsertionSort(vector<int> &nums) {if(nums.size() < 2) return;printf("第0輪:");for(int i = 0; i < nums.size(); i++) {printf("%d",nums[i]);if(i!=nums.size()-1) printf(",");}printf("\n");for(int i = 1; i < nums.size(); i++) {int low = 0;int high = i;int num = nums[i];while(low <= high) {int mid = (low + high) / 2;if(nums[mid] > num) {high = mid - 1;} else {low = mid + 1;}}int j;for(j = i - 1; j > high; j--) {nums[j+1] = nums[j];}nums[j+1] = num; // 查看 printf("第%d輪:",i);for(int i = 0; i < nums.size(); i++) {printf("%d",nums[i]);if(i!=nums.size()-1) printf(",");}printf("\n");}return; } };int main() {vector<int> v;v.push_back(23);v.push_back(76);v.push_back(34);v.push_back(89);v.push_back(90);v.push_back(34);v.push_back(56);v.push_back(18);Solution solution;solution.binaryInsertionSort(v);return 0; }

    希爾排序測試代碼

    #include <stdio.h> #include <vector> using namespace std; class Solution{ public:void ShellSort(vector<int> &nums) {int size = nums.size();int count = 0;// 查看 printf("第0輪:");count++;for(int i = 0; i < nums.size(); i++) {printf("%d",nums[i]);if(i!=nums.size()-1) printf(",");}printf("\n");for(int step = size / 2; step > 0; step /= 2) {for(int i = 0; i < step; i++) {insertSort(nums, size, i, step);}// 查看 printf("第%d輪:",count);count++;for(int i = 0; i < nums.size(); i++) {printf("%d",nums[i]);if(i!=nums.size()-1) printf(",");}printf("\n");}} private:void insertSort(vector<int> &nums, int size, int i, int step){for(int j = i + step; j < size; j+=step) {if(nums[j] < nums[j-step]) {int num = nums[j];int k = j - step;while(k >= 0 && nums[k] > num) {nums[k+step] = nums[k];k -= step;}nums[k+step] = num;}}return;} };int main() {vector<int> v;v.push_back(23);v.push_back(76);v.push_back(34);v.push_back(89);v.push_back(90);v.push_back(34);v.push_back(56);v.push_back(18);Solution solution;solution.ShellSort(v);return 0; }

    所有的插入排序均不是全局有序(全局排序:即每一輪均有一個數字的位置不會改變)

    總結

    以上是生活随笔為你收集整理的【数据结构-排序】1. 图解插入排序三种实现(插入排序/折半排序/希尔排序)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。