************************************************************************************************************************************************************************************************ios
話很少說,直接進入正題:c++
代碼實現以下:(以正序輸出爲例,倒序輸出,僅需對代碼進行適當修改便可)程序員
#include<bits/stdc++.h> #include<algorithm> using namespace std; int a[100055]; int main() { int n,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; } int head; head = 2; while(head<=n) { i = head; while(i>=2&&a[i]<a[i-1]) { if(a[i]<a[i-1])//判斷是否進行交換 { swap(a[i] ,a[i-1]);//調用swap函數 i--; } } head++;//起索引做用,是循環的範圍加1 } for(i=1;i<=n;i++) { cout<<a[i]; } return 0; }
上述代碼的運行結果爲:算法
首先,咱們來理一下上述代碼的思想,上述代碼實際上就是,每次while循環依次比較a[2]與a[1] ; a[3]與a[2] 、a[2]與a[1] ; a[4]與a[3]、a[3]與a[2]、a[2]與a[1] ; ………大小,直到遍歷完數組全部的元素,也就完成了排序。數組
咱們能夠把上述代碼總結成一種模型,即,上述代碼能夠對任意一組數據的任意一段連續數據進行排序(僅需改變上述代碼的初始化條件以及循環結束條件便可實現),而這一思想的典型應用就是 「滾動的榜單」問題。函數
固然,上述代碼也能夠用for循環實現,但我的認爲,用while循環,更能體現其思想本質,尤爲是經過變量head,體現比較範圍的變換。且在實際應用時,我的感受,用while循環實現更加方便。學習
代碼以下(以正序輸出爲例)ui
#include<bits/stdc++.h> #include<algorithm> using namespace std; int a[55]; int main() { int n,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; } int head = 1; while(head<=n) { for(i=head+1;i<=n;i++) { if(a[i]<a[head]) { swap(a[i] ,a[head]); } } head++; } for(i=1;i<=n;i++) { cout<<a[i]; } return 0; }
上述代碼的運行結果爲:spa
上述代碼的思想是:首先,用數組的第一個元素與剩下的元素比較,並將最小的元素調到第一位;而後,用數組的第二個元素與剩下的元素比較,並將最小的元素調到第二位;以此類推,當head等於n時,就完成了排序。設計
上述算法,對於不搞競賽的同窗來講,應該是最經常使用的排序方法了。
上述代碼一樣能夠用for循環實現。
具體代碼以下(以升序形式輸出)
#include<iostream> #include<algorithm> using namespace std; void quicksort(int l ,int r); int a[100055]; int main() { int n,i; cin>>n; for(i=1;i<=n;i++) { cin>>a[i]; } quicksort(1 ,n); for(i=1;i<=n;i++) { cout<<a[i]<<" "; } cout<<endl; return 0; } void quicksort(int l ,int r) { int i,j,m,mid; i = l; j = r;
mid = (l+r)/2; m = a[mid];//將數組分紅兩部分 while(i<=j) {
/***********************************************/
//注意,這裏while裏面的判斷條件爲何不帶上 「=」?
//是爲了防止當出現數組中出現一段相等的數字是,該循環變爲死循環。以下面舉出的例子。 while(a[i]<m) i++; while(a[j]>m) j--;
/***********************************************/ if(i<=j) { swap(a[i] ,a[j]); i++; j--; } } if(j-l>=1)//中止調用函數自己的判斷條件 quicksort(l ,j);//經過調用函數自身,對分開的兩部分,分別進行排序
//同時,因爲i,j通過while循環,均越過了中值mid,故,新範圍是(l ,j),下面的(i,r)同理。 if(r-i>=1)//中止調用函數自己的判斷條件 quicksort(i ,r);//經過調用函數自身,對分開的兩部分,分別進行排序 }
上述代碼運行結果爲:
但當將while循環中的判斷條件帶上等號是,就會出現漏洞,可能使程序變爲死循環,如:
上述代碼實際上體現了二分的思想:首先隨機在數組中選一個數,將一個數組分紅隨機分紅兩部分(這裏我就用區間的中間位置對應的值,實際上,能夠用rand函數隨機生成一個位置,這樣其實更加合理),分別在左,右取大於或等於、小於或等於a[mid]的數,進行交換,直到i,j越過mid值時,一次循環結束。這樣不斷地進行循環,最終便可以實現排序。
快速排序的精髓就在於靈活應用二分的思想,這也正是其運行效率高的緣由之一。
代碼以下:(以升序爲例)
上述代碼運行結果爲:
上述代碼的核心思想是:先將數組利用二分思想屢次進行二等分,而後在從獲得的各個小份數組出發,兩兩遵循在合併的同時按從小到大排序,最終,便可實現排序。
具體圖片以下:(下圖摘自百度百科 ,連接:https://baike.baidu.com/pic/歸併排序/1639015/0/c8177f3e6709c93d673b9ed49d3df8dcd00054c3
fr=lemma&ct=single#aid=0&pic=c8177f3e6709c93d673b9ed49d3df8dcd00054c3)
歸併排序在上述幾種排序方式中應該是最複雜的排序方式了,但其高效的運行效率,以及其包含的重要思想使得做爲一個合格的程序員,或者是搞算法競賽的同窗必須掌握。
到目前爲止,我的感受,對上述歸併排序算法的思想的應用最到位的當屬經典的 「 逆序數的對數」 問題。
除了介紹上述四種經常使用的排序方法外,我還想補充一下關於二分法查找的一下東西。(將一個數加入到一組數裏面後,找出其在這組數裏的位置)
先看代碼實現:(以正序輸入爲例)
以上代碼運行結果爲:
若沒有上述語句,會:
結果是亂碼!!!
因此,咱們在設計二分法的時候,必定要考慮當輸入的值大於已知的最大值這種狀況,固然,解決這個問題的方法不止上面一種,就不一一羅列了。
*************************************************************************************************************************************************************************************************************************
再強調一次,以上代碼均爲 經過各類途徑學習+本身的理解 所得,如若侵權,請告知,覈實以後,必當即刪除!!!
同時本人爲大一菜鳥,上面的樣例均爲自主設置的,如如有誤,還請告知,必當即改正。
本人寫此文章主要目的是對知識點整理,但限於我的水平,如上述表述內容有些許錯誤,或不到位的地方,請各位大佬告知,在下必馬上更改!!!
歡迎大佬們評論,留言。
最後,碼字不易,要是感受還行的話,求求大佬們點個贊吧。