生活随笔
收集整理的這篇文章主要介紹了
几种排序算法的比较
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2018-3-20
我花了18元從App Store里面買了Algorithms,這里面的步驟還是比較容易理解的。
1.冒泡排序
冒泡排序是兩兩相鄰的進行比較,平均時間復雜度是O(n^2),是比較穩定的排序,因為兩個相等的數是不會進行交換的。
#include<iostream>
using namespace std;
const int N =
10;
int x[N+
1]={
33,
25,
4,
23,
65,
31,
57,
8,
6,
32};
void bubbleSort(){
for (
int i=
0;i<N-
1;i++){
for (
int j=
0;j<N-i-
1;j++){
if (x[j]>x[j+
1]){
int t=x[j];x[j]=x[j+
1];x[j+
1]=t;}}}
}
void disPlay(){
for (
int i=
0;i<N-
1;i++){
cout<<x[i]<<
" ";}
cout<<x[N-
1]<<endl;
}
int main(){bubbleSort();disPlay();
return 0;
}
當然,如果說我們原來的數組就是有序的話,那么我們還需要進行那么多次比較,豈不是很浪費時間,所以就有了優化過后的冒泡排序。
#include<iostream>
using namespace std;
const int N =
10;
int x[N+
1]={
33,
25,
4,
23,
65,
31,
57,
8,
6,
32};
bool flag;
void bubbleSort(){
for (
int i=
0;i<N-
1;i++){flag=
false;
for (
int j=
0;j<N-i-
1;j++){
if (x[j]>x[j+
1]){
x[j]=x[j]^x[j+
1];x[j+
1]=x[j]^x[j+
1];x[j]=x[j]^x[j+
1];flag=
true;}}
if (!flag)
break;}
}
void disPlay(){
for (
int i=
0;i<N-
1;i++){
cout<<x[i]<<
" ";}
cout<<x[N-
1]<<endl;
}
int main(){bubbleSort();disPlay();
return 0;
}
其實也就是發現每一個相鄰兩個的順序都ok的話,我們的排序也就結束了。
我們還可以不使用第三個變量來使兩個數進行交換,我們只要使用異或運算即可,一個數和它本身異或的結果為0。
2.快速排序
我們發現冒泡排序需要多次交換,而快排只有在需要的時候才會進行交換。
以一個數為基準(通常是第一個數),把比它大的數放在它的后面,把比它小的數放在它的前面,對前面和后面兩組數實施相同的操作。平均復雜度為O(nlogn),是不穩定的排序。
快排每一次都會有一個數在它正確的位置上。
#include<iostream>
using namespace std;
const int N =
10;
int x[N+
1]={
33,
25,
4,
23,
65,
31,
57,
8,
6,
32};
void quickSort(
int low,
int high){
if (low>=high){
return ;}
int key=x[low],i=low,j=high;
while (i<j){
while (i<j&&x[j]>=key) j--;x[i]=x[j];
while (i<j&&x[i]<=key) i++;x[j]=x[i];}x[i]=key;quickSort(low,i-
1);quickSort(i+
1,high);
}
void disPlay(){
for (
int i=
0;i<N-
1;i++){
cout<<x[i]<<
" ";}
cout<<x[N-
1]<<endl;
}
int main(){quickSort(
0,N-
1);disPlay();
return 0;
}
我們先將第一個數x[low]保存起來為key,先從后往前找,找到第一個小于key的數的下標j,將x[j]賦值給x[low],然后再從前往后找,找到第一個比key大的數的下標i,把x[i]賦值給原來找到的x[j],重復這個過程直到大于key的都在它的后面,小于key的都在它的前面,然后把key保存在”中間的位置”,這是一個遞歸的過程,我們需要對前面和后面的數做相同的處理。
又或者你可以用另一種方法,每次得到大于key的x[i]與小于key的x[j]進行交換,然后最后再將x[low]的值與x[i]進行交換,需要我們注意的是,我們第一個while循環得是對j進行的操作。
這里踩了異或運算的一個坑,兩個相同的數異或的結果是零,那么此時它們兩個是不能用異或運算進行交換的…
#include<iostream>
using namespace std;
const int N =
10;
int x[N+
1]={
33,
25,
4,
23,
65,
31,
57,
8,
6,
32};
void quickSort(
int low,
int high){
if (low>=high){
return ;}
int key=x[low],i=low,j=high;
while (i<j){
while (i<j&&x[j]>=key) j--;
while (i<j&&x[i]<=key) i++;
if (i<j){x[i]=x[i]^x[j];x[j]=x[i]^x[j];x[i]=x[i]^x[j];}}
int t=x[i];x[i]=x[low];x[low]=t;quickSort(low,i-
1);quickSort(i+
1,high);
}
void disPlay(){
for (
int i=
0;i<N-
1;i++){
cout<<x[i]<<
" ";}
cout<<x[N-
1]<<endl;
}
int main(){quickSort(
0,N-
1);disPlay();
return 0;
}
3.插入排序
每次將前面的數看作是有序的,那么問題就變成了向一個有序的序列里插入數字使它們依然保持有序,默認第一個數就是有序的。平均時間復雜度為O(n^2),是一個穩定的排序。
#include<iostream>
using namespace std;
const int N =
10;
int x[N+
1]={
33,
25,
4,
23,
65,
31,
57,
8,
6,
32};
void insertSort(){
int i=
1;
while (i<N){
if (x[i]>=x[i-
1]) {i++;
continue; }
int key=x[i],j=i-
1;
while (x[j]>key&&j>=
0){x[j+
1]=x[j];j--;}
if (j!=i-
1) x[j+
1]=key;i++;}
}
void disPlay(){
for (
int i=
0;i<N-
1;i++){
cout<<x[i]<<
" ";}
cout<<x[N-
1]<<endl;
}
int main(){insertSort();disPlay();
return 0;
}
其實還是比較簡單的,先把當前要插入的數記住為key,然后從后往前進行比較,如果大于key的話,就后移一位,否則的話就把這個數插入進去。
4.選擇排序
從所有記錄中選出最小的一個數據元素與第一個位置的記錄交換;然后在剩下的記錄當中再找最小的與第二個位置的記錄交換,循環到只剩下最后一個數據元素為止。平均時間復雜度為O(n^2),是一個不穩定的排序方法。
#include<iostream>
using namespace std;
const int N =
10;
int x[N+
1]={
33,
25,
4,
23,
65,
31,
57,
8,
6,
32};
void selectSort(){
for (
int i=
0;i<N;i++){
int k=i;
for (
int j=i+
1;j<N;j++){
if (x[j]<x[k]) k=j;}
if (k!=i){
int t=x[k];x[k]=x[i];x[i]=t;}}
}
void disPlay(){
for (
int i=
0;i<N-
1;i++){
cout<<x[i]<<
" ";}
cout<<x[N-
1]<<endl;
}
int main(){selectSort();disPlay();
return 0;
}
注意這里的選擇排序是一個不穩定的排序,如果說我們的序列為:5,7,3,5,2,1,那么我們在得到第一個最小的值的時候就要與第一個5進行交換,此時它們倆的相對順序就不一樣了,所以說是不穩定的排序。
5.希爾排序
這是一種有增量的插入排序,插入排序是以1作為增量,而希爾排序是不斷將增量縮小為1而實現的插入排序,平均時間復雜度為O(n^3/2),是一種不穩定的排序。
#include<iostream>
using namespace std;
const int N =
10;
int x[N+
1]={
33,
25,
4,
23,
65,
31,
57,
8,
6,
32};
void shellSort(){
int i,j,increMent=N/
3+
1;
for (increMent=N/
3+
1;increMent>=
1;increMent=increMent/
3+
1){
for (i=increMent+
1;i<N;i++){
if (x[i]>=x[i-increMent])
continue;
int key=x[i];
for (j=i-increMent;j>=
0&&x[j]>key;j-=increMent){x[j+increMent]=x[j];}
if (j+increMent!=i) x[j+increMent]=key;}
if (increMent==
1)
break;}
}
void disPlay(){
for (
int i=
0;i<N-
1;i++){
cout<<x[i]<<
" ";}
cout<<x[N-
1]<<endl;
}
int main(){shellSort();disPlay();
return 0;
}
和插入排序的方法差不多,唯一的區別就是說這里進行插入排序的數字之間是有間隔的,而這個間隔其實是會影響我們的性能的。
如果說滿足某個條件就退出for循環的話就把他寫在for(;XXXX;)這里,因為它的意思就是在不滿足這個條件時就結束循環。
6.歸并排序
一種分治的思想。將已有序的子序列合并,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合并成一個有序表,稱為二路歸并。平均時間復雜度為O(nlogn),是一種穩定的排序方法。
#include<iostream>
using namespace std;
const int N =
10;
int x[N+
1]={
33,
25,
4,
23,
65,
31,
57,
8,
6,
32},y[N+
1];
void mergeSort(
int low,
int high){
if (low>=high){
return ;}
int mid=(low+high)/
2;mergeSort(low,mid);mergeSort(mid+
1,high);
int i=low,j=mid+
1,k=low;
while (i<=mid&&j<=high){
if (x[i]<=x[j]) y[k++]=x[i++];
else y[k++]=x[j++];}
while (i<=mid) y[k++]=x[i++];
while (j<=high) y[k++]=x[j++];
for (
int i=low;i<=high;i++) x[i]=y[i];
}
void disPlay(){
for (
int i=
0;i<N-
1;i++){
cout<<x[i]<<
" ";}
cout<<x[N-
1]<<endl;
}
int main(){mergeSort(
0,N-
1);disPlay();
return 0;
}
7.堆排序
每次都取堆頂的元素,將其放在序列最后面,然后將剩余的元素重新調整為最大堆,依次類推,最終得到排序的序列。它是一種不穩定的排序。
#include<iostream>
using namespace std;
const int N =
10;
int x[N+
1]={
33,
25,
4,
23,
65,
31,
57,
8,
6,
32},y[N+
1];
void heapAdjust(
int s,
int e){
int temp=x[s],j;
for (j=
2*s;j<=e;j*=
2){
if (j<e&&x[j]<x[j+
1]) ++j;
if (temp>=x[j])
break;x[s]=x[j];s=j;} x[s]=temp;
}
void heapSort(){
for (
int i=N/
2-
1;i>=
0;i--){heapAdjust(i,N-
1);}
for (
int i=N-
1;i>
0;i--){
int t=x[
0];x[
0]=x[i];x[i]=t;heapAdjust(
0,i-
1);}
}
void disPlay(){
for (
int i=
0;i<N-
1;i++){
cout<<x[i]<<
" ";}
cout<<x[N-
1]<<endl;
}
int main(){heapSort();disPlay();
return 0;
}
總結
以上是生活随笔為你收集整理的几种排序算法的比较的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。