【数据结构与算法】- 排序(算法)
目錄
一:編寫雙向冒泡排序算法,在正反兩個方向交替進行掃描,即第一趟把關鍵字最大的元素放在序列的最后面,第二趟把關鍵字最小的元素放在序列的最前面,如此反復進行
二:已知線性表按順序存儲,且每個元素都是不相同的整數型元素,設計把所有奇數移動到所有偶數前面的算法
三:試著重新編寫 快速排序的劃分算法,使之每次選取的樞軸值都是隨機地從當前子表中選擇的
四:試著編寫一個算法,使之能夠在數組L[1...n]中找到第k小的元素(即從小到大排序后處于第k個位置的元素)
五:荷蘭國旗問題:設有一個僅由紅,白,藍三種顏色的條塊組成的條塊序列,請編寫算法,使得這些條塊按紅 白 藍的順序排好,即排成荷蘭國旗圖案
六:已知由n(n>=2)個正整數構成的集合A={ak|0<=k},將其劃分成為兩個不相交的子集a1和a2。元素個數分別是n1和n2,a1和a2中的元素之和分別為s1和s2,設計一個算法,滿足|n1-n2|最小且|s1-s2|最大
七:編寫一個算法,在基于單鏈表表示的待排序關鍵字序列上進行簡單選擇排序
八:試著設計一個算法,判斷一個數據序列是否構成一個小根堆
九:設順序表用數組A[ ]表示,表中元素存儲在數組下標1 -? m+n范圍內,前m個元素遞增有序,后n個元素遞增有序,設計一個算法,使得整個順序表有序
十:有一種簡單的排序算法,稱為計數排序,這種排序算法對一個待排序的表(用數組表示)進行排序,并將排序結果存放到另一個新的表中,必須注意的是,表中所有待排序的關鍵碼互不相同,計數排序算法針對表中的每個記錄,掃描待排序的表一趟,統計表中有多少個記錄的關鍵碼比該記錄的關鍵碼小,假設針對某個記錄統計出的計數值為c,則這個記錄在新有序表中的合適存放位置為c
十一:設有一個數組中存放了一個無序的關鍵序列K1,K2,..Kn,現要求將Kn放在將元素排序后的正確位置上,試著編寫實現該功能的算法,要求比較關鍵字的次數不超過n?
一:編寫雙向冒泡排序算法,在正反兩個方向交替進行掃描,即第一趟把關鍵字最大的元素放在序列的最后面,第二趟把關鍵字最小的元素放在序列的最前面,如此反復進行。
#include<iostream> using namespace std;//雙向冒泡 void bsort(int a[],int n) {int i;//范圍的左右兩端int low=0,high=n-1;//一趟是否交換過 初始化bool flag = true;//循環條件 左端<右端 并且一趟有交換while(low<high&&flag){//排序前 默認一趟沒有交換flag = false;//從前向后交換for(i=low;i<high;i++){if(a[i]>a[i+1]){swap(a[i],a[i+1]);flag = true;}}high--;//從后向前交換for(i=high;i>low;i--){if(a[i]<a[i-1]){swap(a[i],a[i-1]);flag = true;}}low++;} }int main() {int a[10] = {7,5,9,2,6,4,3,8,1};bsort(a,9);for(int i=0;i<9;i++){cout<<a[i]<<" ";}return 0; }二:已知線性表按順序存儲,且每個元素都是不相同的整數型元素,設計把所有奇數移動到所有偶數前面的算法
#include<iostream> using namespace std;void Move(int a[],int n) {//查找范圍的左右兩端int i=0,j=n-1;//循環遍歷條件while(i<j){//從前向后找偶數位置while(i<j&&a[i]%2==1) i++;//從后向前找奇數位置while(i<j&&a[j]%2==0) j--;//若偶數在奇數前面 交換if(i<j){//同時更新范圍的左右端swap(a[i],a[j]);i++;j--;}} }int main() {int a[10] = {7,5,9,2,6,4,3,8,1};Move(a,9);for(int i=0;i<9;i++){cout<<a[i]<<" ";}return 0; }三:試著重新編寫 快速排序的劃分算法,使之每次選取的樞軸值都是隨機地從當前子表中選擇的
核心代碼?
void Partiton2(int a[],int low,int high,) {//獲取隨機下標int root=low+rand()%(high-low+1);//交換到第一個swap(a[low],a[root]);//i一開始指向low位置int i = low;//從第二個開始遍歷到結束int p = a[low];for(int j=low+1;j<=high;j++){//如果小于基數值if(a[j]<p)swap(a[++i],a[j]);//交換到前面去}//將基準元素插入到最終的位置swap(a[low],a[i]);//返回基準元素的位置return i; }四:試著編寫一個算法,使之能夠在數組L[1...n]中找到第k小的元素(即從小到大排序后處于第k個位置的元素)
#include<iostream> using namespace std;int min_k(int a[],int low,int high,int k) {//快速排序劃分算法//i一開始指向low位置int i=low;//從第二個開始遍歷到結束int p=a[low];for(int j=low+1;j<=high;j++){//如果小于基準值if(a[j]<p)swap(a[++i],a[j]);//交換到前面去}//將基準元素插入到最終的位置swap(a[low],a[i]);//返回到基準元素的位置if(i==k) return a[i];//若最后基準的位置為k的話 那么基準就是第k小else if(i>k) return min_k(a,low,i-1,k);//若最后基準的位置>k的話 那么基準左邊遞歸去找else return min_k(a,i+1,high,k);//若最后基準的位置<k的話 那么基準右邊遞歸去找 } int main() {int a[10] = {0,7,5,9,2,6,4,3,8,1};cout<<min_k(a,1,9,8)<<endl;return 0; }五:荷蘭國旗問題:設有一個僅由紅,白,藍三種顏色的條塊組成的條塊序列,請編寫算法,使得這些條塊按紅 白 藍的順序排好,即排成荷蘭國旗圖案
#include<iostream> using namespace std;//按照負數0 正數來排數組 void num(int a[],int n) {//三個指針的指向 初始化int i=0,j=0,k=n-1;//循環體 j<=kwhile(j<=k){int v;if(a[j]>0) v=1;else if(a[j]==0) v=0;else v=-1;//switch判斷a[j]的值switch(v){//負數 和i交換case -1:swap(a[i],a[j]);i++;j++;break;//0 遍歷指針+1case 0:j++;break;//正數 和k交換case 1:swap(a[j],a[k]);k--;break;}} }int main() {int a[9] = {0,-1,-2,0,0,3,-4,1};num(a,8);for(int i=0;i<8;i++){cout<<a[i]<<" ";}return 0; }六:已知由n(n>=2)個正整數構成的集合A={ak|0<=k<n},將其劃分成為兩個不相交的子集A1和A2。元素個數分別是n1和n2,A1和A2中的元素之和分別為S1和S2,設計一個算法,滿足|n1-n2|最小且|S1-S2|最大
#include<iostream> using namespace std;//快排 void seta(int a[],int n,int low,int high) {//非遞歸int flag=1;//取中間值 后面與基準值進行比較int k=(high-low)/2;//非遞歸條件while(flag){//快排//i一開始指向low位置int i=low;//從第二個開始遍歷到結束int p=a[low];for(int j=low+1;j<=high;j++){//如果小于基準值if(a[j]<p)//交換到前面去swap(a[++i],a[j]);}//將基準元素插入到最終的位置swap(a[low],a[i]);//返回基準元素的位置//如果基準值剛好等于s1的右端 結束if(i==k-1) flag=0;//如果基準值小于 則在右端進行快排 繼續找到中間值的位置else if(i<k-1) low=i+1;//否則在左端else high = i-1;}//計算兩個集合的和int s1=0,s2=0;for(int i=0;i<k;i++){s1+=a[i];cout<<"s1="<<a[i]<<" ";}cout<<endl;for(i=k;i<n;i++){s2+=a[i];cout<<"s2="<<a[i]<<" ";}cout<<endl;cout<<abs(s1-s2)<<endl; }int main() {int a[9]={0,-1,-2,0,-10,3,-4,1};seta(a,8,0,8);return 0; }七:編寫一個算法,在基于單鏈表表示的待排序關鍵字序列上進行簡單選擇排序
#include<iostream> using namespace std;//鏈表存儲結構 typedef struct lnode{int data;struct lnode *next; }lnode,*linklist;int a[10]={7,5,9,2,6,4,3,8,1}; int n=9;void buildlist(lnode *L) {lnode *s,*r=L;r->data=a[0];if(n==1) r->next=NULL;else{for(int i=1;i<n;i++){s=(lnode *)malloc(sizeof(lnode));s->data=a[i];r->next=s;r=r->next;}r->next=NULL;} }void disp(lnode *L) {lnode *s=L;while(s){cout<<(s->data)<<" ";s=s->next;}cout<<endl; }//簡單選擇排序 void selectsort(linklist &l) {//五個指針 遍歷表的指針的初始化lnode *h = l;lnode *p,*s,*r,*q;//將表置空l= NULL;//最外面的循環條件while(h!=NULL){//最大節點和工作指針的初始化s=p=h;//前驅節點的初始化q=r=NULL;//每一趟開始遍歷while(p!=NULL){//碰到更大的節點if(p->data>s->data){//更新最大節點的位置s=p;//更新最大節點的前驅r=q;}q=p;p = p->next;//工作指針向后遍歷時前驅指針和工作指針向后移}//若最大的是表頭 將遍歷表的指針后移if(s==h) h = h->next;else{r->next = s->next;}//插入結果鏈表當中s->next = l;//更新結果鏈表的頭l=s;} }int main() {lnode L;lnode *l = &L;buildlist(l);selectsort(l);disp(l);return 0; }八:試著設計一個算法,判斷一個數據序列是否構成一個小根堆
#include<iostream> using namespace std;//判斷是不是小根堆 int is_min(int a[],int len) {//最后的序號為偶數if(len%2==0){//判斷單只節點if(a[len/2]>a[len]) return 0;//判斷雙支節點for(int i=len/2;i>=1;i--){if(a[i]>a[2*i]||a[i]>a[2*i-1])return 0;}}else{//為奇數for(int i=len/2;i>=1;i--){//判斷雙支節點if(a[i]>a[i*2]||a[i]>a[i*2+1])return 0;}}return 1; }int main() {int a[8]={1,1,3,2,5,4,0};cout<<is_min(a,6)<<endl;return 0; }九:設順序表用數組A[ ]表示,表中元素存儲在數組下標1 -? m+n范圍內,前m個元素遞增有序,后n個元素遞增有序,設計一個算法,使得整個順序表有序
#include<iostream> using namespace std;void insertsort(int a[],int m,int n) {//兩個遍歷指針int i,j;//第一個遍歷范圍for(i=m+1;i<=m+n;i++){//復制哨兵a[0]=a[i];for(j=i-1;a[j]>a[0];j--){a[j+1]=a[j];//后移}a[j+1]=a[0];//插入哨兵值} }int main() {int a[8]={0,1,3,5,7,2,4,9};insertsort(a,4,3);for(int i=1;i<=7;i++) cout<<a[i]<<" ";return 0; }十:有一種簡單的排序算法,稱為計數排序,這種排序算法對一個待排序的表(用數組表示)進行排序,并將排序結果存放到另一個新的表中,必須注意的是,表中所有待排序的關鍵碼互不相同,計數排序算法針對表中的每個記錄,掃描待排序的表一趟,統計表中有多少個記錄的關鍵碼比該記錄的關鍵碼小,假設針對某個記錄統計出的計數值為c,則這個記錄在新有序表中的合適存放位置為c
#include<iostream> using namespace std;void countsort(int a[],int b[],int n) {//遍歷每一趟int count=0;for(int i=0;i<n;i++){//找到每個元素小的個數count = 0;for(int j=0;j<n;j++){if(a[j]<a[i]) count++;}b[count] = a[i];} } int main() {int a[6]={3,5,7,2,4,9},b[6];countsort(a,b,6);for(int i=0;i<6;i++) cout<<b[i]<<" ";return 0; }十一:設有一個數組中存放了一個無序的關鍵序列K1,K2,..Kn,現要求將Kn放在將元素排序后的正確位置上,試著編寫實現該功能的算法,要求比較關鍵字的次數不超過n?
#include<iostream> using namespace std;int quicksort(int a[],int low,int high) {//i一開始指向high位置int i=high;//從倒數第二個開始遍歷到頭int p=a[high];for(int j=high-1;j>=0;j--){//如果大于基準值if(a[j]>p) swap(a[--i],a[j]);//交換到后面去}//將基準元素插入到最終的位置swap(a[high],a[i]);//返回基準元素的位置return i; }int main() {int a[5]={3,5,7,2,4};cout<<quicksort(a,0,4)<<endl;return 0; }總結
以上是生活随笔為你收集整理的【数据结构与算法】- 排序(算法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux服务器通过代理连接网络
- 下一篇: 如何在 7 分钟内黑掉 40 家网站?