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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

C++排序算法实现(更新中)

發(fā)布時間:2023/11/27 生活经验 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++排序算法实现(更新中) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

比較排序法:如冒泡排序、簡單選擇排序、合并排序、快速排序。其最優(yōu)的時間復(fù)雜度為O(nlogn)。
其他排序法:如桶排序、基數(shù)排序等。時間復(fù)雜度可以達到O(n)。但試用范圍有要求。

桶排序:排序的數(shù)組元素跨距不能很大。因為跨距很大的話,會開辟大量的內(nèi)存。
基數(shù)排序:只適用于整數(shù)。


圖片來自博客:
https://www.cnblogs.com/wuxiangli/p/6399266.html

排序的穩(wěn)定性

考察排序算法的時候有一個很重要的特性,就是算法的穩(wěn)定性:假定在待排序的記錄序列中,存在多個具有相同的關(guān)鍵字的記錄,若經(jīng)過排序,這些記錄的相對次序保持不變,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,則稱這種排序算法是穩(wěn)定的;否則稱為不穩(wěn)定的。

1、冒泡排序(O(n2))

1.1、普通冒泡排序

依次將最小的數(shù)冒泡到第一位。流程如下圖所示。

void print_array(int* a)
{for(int i = 0;i<8;i++)cout<<a[i]<<"  ";cout<<endl;
}
int main()
{int a[8] = {10,23,56,12,12,0,2,15};for(int i = 0;i<8;i++){for (int j = 7; j > i; j--){if(a[j] < a[j-1]){int temp = a[j];a[j] = a[j-1];a[j-1] = temp;}}print_array(a);}
}

1.2、帶標記為的冒泡排序

如果在某次冒泡的過程中,沒有發(fā)生數(shù)據(jù)交換,說明已經(jīng)排好序了,沒有必要繼續(xù)進行。因此可以設(shè)置一個標志位:bool flag。

void print_array(int* a)
{for(int i = 0;i<8;i++)cout<<a[i]<<"  ";cout<<endl;
}
int main()
{int a[8] = {10,23,56,12,12,0,2,15};bool flag = true;for(int i = 0;i<8 && flag;i++){// 如果以后沒有數(shù)據(jù)交換,flag就會是falseflag = false;for (int j = 7; j > i; j--){if(a[j] < a[j-1]){// 發(fā)生數(shù)據(jù)交換時,標志位置為true。flag = true;int temp = a[j];a[j] = a[j-1];a[j-1] = temp;}}print_array(a);}
}

2、簡單選擇排序(O(n2))

從第一位開始,每次選擇最小的數(shù)據(jù),和開始時的數(shù)據(jù)進行交換。

void print_array(int* a)
{for(int i = 0;i<8;i++)cout<<a[i]<<"  ";cout<<endl;
}
int main()
{int a[8] = {10,23,56,12,12,0,2,15};for(int i = 0;i<7;i++){int min = i;for(int j = i+1;j<8;j++){if(a[j] < a[min])min = j;}if(min != i){int temp = a[min];a[min] = a[i];a[i] = temp;}}print_array(a);
}

3、歸并排序(nlogn)

歸并排序的思路為:將數(shù)組不斷的分為兩部分。如一個長度為8的數(shù)組—>長度為4—>長度為2—>長度為1。然后再兩兩合并。在合并的過程中,數(shù)組已經(jīng)有序了,因此時間復(fù)雜度會降低。

// 合并兩個數(shù)組的函數(shù)
void Merge(int* a,int left1,int right1,int left2,int right2)
{// 由于后面會用到left1,left2的原值,因此這里先備份一個。int temp_left1 = left1;int temp_left2 = left2;int n = (right1 - left1 + 1) + (right2 - left2 + 1);vector<int> result;// 此時兩個數(shù)組已經(jīng)是有序的,合并的過程中,有一個數(shù)組到頭后就停止while(left1 <= right1 && left2 <= right2){if(a[left1] <= a[left2])result.push_back(a[left1++]);elseresult.push_back(a[left2++]);}// 遍歷剩下的部分while(left1 <= right1)result.push_back(a[left1++]);while(left2 <= right2)result.push_back(a[left2++]);// 放到數(shù)組a對應(yīng)的部分for(int i = 0;i<n;i++){a[temp_left1 + i] = result[i];}}
void Msort(int* a,int left,int right)
{if(left >= right) return;int medium = (left + right) / 2;// 分Msort(a,left,medium);Msort(a,medium+1,right);// 合Merge(a,left,medium,medium+1,right);
}
int main()
{int a[8] = {1,2,54,64,125,94,64,132};Msort(a,0,7);for(int i = 0;i<8;i++){cout<<a[i]<<"  ";}
}

4、快速排序(nlogn)

其思想為選一個數(shù)字,將小于該數(shù)字的值放在左邊,將大于該數(shù)字的值放在右邊。再將該數(shù)字的左右兩側(cè)的數(shù)組重復(fù)該過程。

思路由一篇博文提供,建議閱讀以下,比我寫的詳細很多。鏈接如下:
https://blog.csdn.net/qq_28584889/article/details/88136498

// 第一個數(shù)大小記為temp。將小于temp的放在左邊,將大于temp的放在右邊
// 返回排序后temp在數(shù)組中的位置。
int partition(int* a,int left,int right)
{int temp = a[left];int i = left,j = right;while(i < j){while(a[j] >= temp && i < j)j--;while(a[i] <= temp && i < j)i++;if(i < j){int nums = a[i];a[i] = a[j];a[j] = nums;}}a[left] = a[i];a[i] = temp;return i;
}
void quickSort(int* a,int left,int right)
{if(left >= right) return;// pos為排序后,第一個數(shù)字在數(shù)組中的位置// 如:數(shù)組為4 2 1 9 6 5 8 7// partition后變?yōu)? 2 4 9 6 5 8 7// 則pos為4的位置:2int pos = partition(a,left,right);// 對左邊排序quickSort(a,left,pos-1);// 對右邊排序quickSort(a,pos+1,right);
}
int main()
{int a[9] = {2,6,5,9,8,4,1,3,7};quickSort(a,0,8);for(int i = 0;i<9;i++)cout<<a[i]<<"  ";
}

桶排序(O(n))

參考的一下博客,讀者可自行閱讀。
(1)https://blog.csdn.net/bqw18744018044/article/details/81738883?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control
(2)https://www.bilibili.com/video/av17940595?from=search&seid=4032616244052566693

void bucket_sort(double* a)
{vector<double> bucket[10];for(int i = 0;i<10;i++){int bi = 10 * a[i];bucket[bi].push_back(a[i]);}int pos = 0;for(int i = 0;i<10;i++){if(!bucket[i].empty()){sort(bucket[i].begin(),bucket[i].end());for(int j = 0;j<bucket[i].size();j++){a[pos] = bucket[i][j];pos++;}}}
}
int main()
{double a[10] = {0.2,0.5,0.65,0.59,0.62,0.35,0.48,0.98,0.84,0.56};bucket_sort(a);for(int i = 0;i<10;i++)cout<<a[i]<<"  ";
}

基數(shù)排序(O(d*(n+r)))

參考博客:
https://blog.csdn.net/u012580566/article/details/47702955

基數(shù)排序就是分別按個位數(shù)、十位數(shù)…進行排序。
如:
14 37 56 79 93 78 12 65 30
按個位數(shù)排完后為:
30 12 93 14 65 56 37 78 79
按十位數(shù)排完后為:
12 14 30 37 56 65 78 79 93
排序完成。

int get_max_bit(int* data,int n)
{int num = 1;for(int i = 0;i<n;i++){int bit = 0;int temp_val = data[i];while(temp_val != 0){temp_val /= 10;bit++;}if(bit > num)num = bit;}return num;
}
void max_sort(int* data,int n)
{int tmp[n];int count[10];int num = get_max_bit(data,n);int radio = 1;for(int i = 1;i<=num;i++){// 每次分配前清空計數(shù)器for(int j = 0; j < 10; j++)count[j] = 0;// 統(tǒng)計每個桶中的記錄數(shù)for(int j = 0; j < n; j++){int k = (data[j] / radio) % 10;count[k]++;}// count[j]中存儲尾數(shù)為0~j的數(shù)字的個數(shù)for(int j = 1; j < 10; j++)count[j] = count[j - 1] + count[j];// 將所有桶中記錄依次收集到tmp中for(int j = n - 1; j >= 0; j--){int k = (data[j] / radio) % 10;tmp[count[k] - 1] = data[j];count[k]--;}// 將臨時數(shù)組tmp的內(nèi)容復(fù)制到data中for(int j = 0; j < n; j++)data[j] = tmp[j];radio = radio * 10;}
}int main()
{int data[11] = { 73, 22, 93, 43, 55, 14, 28, 65, 39, 81, 196 };max_sort(data,11);for(int i = 0;i<11;i++)cout<<data[i]<<"  ";return 0;
}

時間復(fù)雜度:
設(shè)最高位數(shù)為d位,基數(shù)為r(如基數(shù)為10,即10進制,最大有10種可能,即最多需要10個桶來映射數(shù)組元素),一共n個數(shù)。由代碼可見,時間復(fù)雜度為:O(d(n+r))。空間復(fù)雜度為O(dr+n)。

總結(jié)

以上是生活随笔為你收集整理的C++排序算法实现(更新中)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。