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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

常见排序算法(比较排序)及比较

發布時間:2025/3/15 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 常见排序算法(比较排序)及比较 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
#include<iostream> using?namespace?std; #include<assert.h>//穩定性:指兩個相同數排序后位置是否變化 //冒泡排序思想:相鄰兩數據比較交換,外層循環控制次數,內層比較?? //void?BubbleSort(int?*a,?size_t?len) //{ // assert(a); // for?(size_t?i?=?0;?i?<?len?-?1;?++i) // {???//相鄰位置數據進行比較,每趟排序都會排出一個最大或最小數 // for?(size_t?j?=?0;?j?<?len?-?i?-?1;?++j) // { // if?(a[j]?>?a[j?+?1]) // { // swap(a[j],?a[j?+?1]); // } // } // } //} // //雞尾酒排序思想:即就是雙向冒泡排序,一趟排序就可以找到一個最大的和最小元素 void?cooktail_sort(int?*arr,?size_t?size) {assert(arr);int?tail?=?size?-?1;int?i,?j?;for?(i?=?0;?i?<?tail;?++i){for?(int?j?=?tail;?j>i;?--j){if?(arr[j]?<?arr[j?-?1]){swap(arr[j],?arr[j?-?1]);}}++i;for?(j?=?i;?j?<?tail;?++j){if?(arr[j]>arr[j?+?1])swap(arr[j],?arr[j?+?1]);}--tail;} } //思想:將當前位置的下一個數據插入到前邊以有序的塊中,再將該數與前邊有序的數據逐一比較。 //每插入一個該位置以前的數據都已有序 //void?InsertSort(int?*a,?size_t?len)//插入排序 //{ // assert(a); // for?(size_t?i?=?0;?i?<?len-1;?++i)//當i=len-1時,tmp訪問的位置越界 // { // int?end?=?i; // int?tmp?=?a[end?+?1]; // while?(end?>=?0?&&?a[end]>tmp)//最后一次進去end=0位置要比 // { // a[end?+?1]?=?a[end]; // --end; // } // a[end?+?1]?=?tmp; // } //} //思想:將一個數組分成兩半,再將每一半分半,遞歸類推,當分出來的只有一個數據時,可認為該小組組內已經有序,然后合并相鄰小組,即先遞歸分解數列,在合并數列 void?Mergesort(int?*arr,?int?begin1,?int?end1,?int?begin2,?int?end2) {//assert(arr);//if?(begin1?>=?end1?||?begin2?>=?end2)// return;//int?one?=?end1?-?begin1;//int?two?=?end2?-?begin2;//int?*L?=?new?int[one];//開辟兩個數組,一個保存前半部分,一個保存后半部分//int?*R?=?new?int[two];//int?i?=?0,?j?=?0;//for?(;?i?<?one;?++i)//{// L[i]?=?arr[begin1?+?i];//}//for?(i=0;?i?<?two;?++i)//{// R[i]?=?arr[begin2?+?i];//}//int?index?=?begin1;//for?(i?=?0,?j?=?0;?index?<?end2&&i<one&&j<two;?++index)//{// if?(L[i]?<=?R[j])// {// arr[index]?=?L[i];// ++i;// }// else?// {// arr[index]?=?R[j];// ++j;// }//}//if?(i?<?one)//如果一個子序已排完,將剩另一個余的數據直接連接到后邊//{// for?(int?k?=?i;?k?<?one;?++k)// arr[index++]?=?L[k];//}//else//{// for?(int?k?=?j;?k?<two;?++k)// arr[index++]?=?R[k];//}//delete[]?L;//delete[]?R; } //void?_merge_sort(int?*arr,?int?begin,?int?end) //{ // assert(arr); // if?(begin?+?1?<?end) // { // int?mid?=?begin?+?((end?-?begin)?>>?1); // _merge_sort(arr,?begin,?mid); // _merge_sort(arr,?mid,?end); // Mergesort(arr,?begin,?mid,?mid,?end); // //memcpy(src?+?begin,?dst?+?begin,?(end?-?begin)*sizeof(int)); // } // else // return; //} //兩個同樣數組,將源數組按序放入目標數組中 void?Mergesort(int?*src,int?*dst,?int?begin1,int?end1,int?begin2,int?end2) {assert(src&&dst);size_t?index?=?begin1;//兩個同樣大小的數組while?(begin1?<?end1?&&?begin2?<?end2){if?(src[begin1]?<?src[begin2]){dst[index++]?=?src[begin1++];}else{dst[index++]?=?src[begin2++];}}if?(begin1?<?end1){while?(begin1?<?end1){dst[index++]?=?src[begin1++];}}else{while?(begin2?<?end2){dst[index++]?=?src[begin2++];}} }void?_merge_sort(int?*src,?int?*dst,?int?begin,?int?end) {assert(src?&&?dst);if?(begin?+?1?<?end){int?mid?=?begin?+?((end?-?begin)?>>?1);_merge_sort(src,?dst,?begin,?mid);_merge_sort(src,?dst,?mid?,?end);Mergesort(src,?dst,?begin,?mid,?mid,?end);memcpy(src?+?begin,?dst?+?begin,?(end?-?begin)*sizeof(int));}elsereturn; }void?_Merge_sort(int*?src,?size_t?size) {int*?dst?=?new?int[size];_merge_sort(src,?dst,?0,?size);delete[]?dst; }//思想:采用分治法思想,選定一個基數,通過一趟排序將要排序的數組一分為二,其中基數前的數據都比它小,基數后的數據都比它大,然后在將這兩部分數據分別進行快排 int?QSort(int?*a,?int?left,?int?right)//快速排序 {assert(a);if?(left?>=?right)return?left;int?key?=?a[right];int?begin?=?left;int?end?=?right-1;while?(begin?<?end){while?(begin?<?end?&&?a[begin]?<=?key)begin++;while?(begin?<?end?&&?a[end]?>?key)end--;if?(begin?<?end)swap(a[begin],?a[end]);}if?(a[end]?>=?a[right])swap(a[end],?a[right]);return?end; }//void?QuiSort(int*?a,?int??left,?int?right)//挖坑法 //{ // assert(a); // if?(right?<=?left) // return; // int?tmp?=?a[left]; // int?begin?=?left; // int?end?=?right; // while?(begin?<?end) // { // while?(begin?<?end&&a[end]?>=?tmp) // end--; // if?(begin?<?end) // { // a[begin++]?=?a[end]; // } // while?(begin?<?end&&a[begin]?<=?tmp) // begin++; // if?(begin?<?end) // { // a[end--]?=?a[begin]; // } // } // a[begin]?=?tmp; // QuiSort(a,?left,?begin?-?1); // QuiSort(a,?begin?+?1,?right); //}void?QuickSort(int?*a,?int?left,int?right) {assert(a);if?(left?<?right){int?mid?=?QSort(a,?left,?right);QuickSort(a,?left,?mid?-?1);QuickSort(a,?mid?+?1,?right);} }//思想:第一次查找最小元素所在位置的下標,與第一個元素交換,之后查找次小元素下標,與第二個元素交換,以此類推 //void?SelectSort(int*?a,?size_t?len)//選擇排序 //{ // assert(a); // size_t?min_index?; // for?(size_t?i?=?0;?i?<?len;?++i) // { // min_index?=?i; // for?(size_t?j?=?i+1;?j?<?len?;?++j) // { // if?(a[min_index]?>=?a[j]) // { // min_index?=?j;//找最小元素所在的下標 // } // } // swap(a[min_index],?a[i]);//讓最小元素位于第i個位置 // } //}//思想:將數組按某個增量gap分成若干組,每組中記錄的下標相差gap,對每組中全部元素進行排序??//,然后用一個較小增量再進行上述循環排序,當增量減到1時,整個要排序的數被分成單個組,排序完成 void?Shell_sort(int?*a,size_t?size) {assert(a);int?gap?=?size?/?3?+?1;while?(1){for?(int?i?=?0;?i?<?size?-?gap;?++i){int?end?=?i;int?tmp?=?a[end?+?gap];while?((a[end]?>?tmp)&&end?>=?0){a[end+gap]?=?a[end];end?-=?gap;}a[end?+?gap]?=?tmp;}if?(gap?==?1)break;gap?=?gap?/?3?+?1;//保證gap最后為1時能執行} }void?TestSelectSort() {int?a[10]?=?{?9,?1,?3,?4,?8,?6,?0,?2,?5,?0?};int?len?=?sizeof(a)?/?sizeof(a[0]);cout?<<?"before:";for?(int?i?=?0;?i?<?len;?++i){cout?<<?a[i]?<<?"?";}cout?<<?endl;Shell_sort(a,len);//QuickSort(a,?0,?9);//SelectSort(a,?10);cout?<<?"after:?";for?(int?i?=?0;?i?<?len;?++i){cout?<<?a[i]?<<?"?";}cout?<<?endl; } void?TestMergeSort() {int?a[10]?=?{?9,?1,?3,?4,?8,?6,?7,?2,?5,?0?};int?len?=?sizeof(a)?/?sizeof(a[0]);cout?<<?"before:";for?(int?i?=?0;?i?<?len;?++i){cout?<<?a[i]?<<?"?";}cout?<<?endl;//_merge_sort(a,0,?len);_Merge_sort(a,?len);cout?<<?"after:?";for?(int?i?=?0;?i?<?len;?++i){cout?<<?a[i]?<<?"?";}cout?<<?endl; } //堆排序思想:先建成一個大堆或小堆,堆頂元素是最大(最小),讓堆頂元素與最后一個元素交換,數組長度-1,然后向下調整一次,重復上述循環 //template<class?T> //class?Heap //{ //public: // Heap(T*?a,?size_t?size) // { // for?(size_t?i?=?0;?i?<?size;?++i) // { // _array.push_back(a[i]); // } // for?(int?i?=?(_array.size()?-?2)?/?2;?i?>=?0;--i) // { // AdjustDown(i,_array.size()); // } // } // // void?AdjustDown(int?root,int?size) // { // size_t?lchild?=?2?*?root?+?1; // while?(lchild?<?size) // { // if?((lchild?+?1?<?size)?&&?_array[lchild?+?1]?<?_array[lchild]) // { // lchild++; // } // if?(_array[lchild]?<?_array[root]) // { // swap(_array[lchild],?_array[root]); // root=lchild; // lchild?=?2?*?root?+?1; // } // else // break; // } // } // // void?AdjustUp(size_t?child) // { // size_t?root?=?(child?-?1)?/?2; // while?(child?>?0)//若root和child為size_t型,永遠都不會小于0,因此不能用它為循環條件 // { // if?(_array[child]?<?_array[root]) // { // swap(_array[child],?_array[root]); // child?=?root; // root?=?(child?-?1)?/?2; // } // else // break; // } // } // // void?push_elem(const?T&x) // { // _array.push_back(x); // AdjustUp(_array.size()?-?1); // } // // void?Pop_elem() // { // swap(_array[0],?_array[(_array.size()?-?1])); // _array.pop_back();//將堆頂元素與最后一個元素交換并刪除,再進行向下調整 // AdjustDown(0); // } // // void?Heap_Sort() // { // int?size?=?_array.size(); // while?(size>0) // { // swap(_array[0],?_array[size-1]); // cout?<<?_array[size?-?1]?<<?"?"; // //_array.pop_back(); // AdjustDown(0,size-1); // --size; // } // } // void?Display() // { // cout?<<?"heap?is:"; // for?(int?i?=?0;?i?<?_array.size();?++i) // { // cout?<<?_array[i]?<<?"?"; // } // cout?<<?endl; // } //protected: // vector<T>?_array; // //}; //

算法的適用場景及比較:

比較排序:(1)插入(直接插入、希爾排序)、(2)選擇(選擇排序、堆排序)、(3)交換(冒泡排序、快排)(4)外排序(歸并)

1)時間復雜度:

平均性能為O(N^2):插入、選擇、冒泡

數據規模小時:直接插入排序較好

數據規模大時:冒泡排序時間代價最高

平均性能為O(NlgN):堆、快速、歸并

數據規模大時:適用堆排序(例:在一千萬個數中找最小的前100個數)

數據規模小時:快速排序較好,當小到一定區間使用插入排序

希爾排序平均時間復雜度為O(N^1.3)

穩定性指的是兩個相同的數排序后位置是否變化,若無變化則穩定

2).穩定性分析:

穩定:冒泡、插入、歸并

不穩定:選擇、希爾、堆、快排




轉載于:https://blog.51cto.com/10541559/1773689

總結

以上是生活随笔為你收集整理的常见排序算法(比较排序)及比较的全部內容,希望文章能夠幫你解決所遇到的問題。

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