氣泡排序中交換次數與比較次數
阿新 • • 發佈:2019-01-29
氣泡排序的過程中每次交換就是消除一個逆序對,而比較次數由其外層迴圈確定,因為內層是肯定迴圈至結束的。
用了歸併排序求逆序對,樹狀陣列求一個數的最大逆序對數。內部迴圈的次數為n-1,n-2.....n-m 數列求和。
程式碼如下,大家可以測試下。
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<ctime> #define lowbit(x) (-x)&(x) #define N 110 #define M 100 using namespace std; int num[N]; int use[N]; int tmp[N]; int vis[N]; int sum[N]; int antinum; void mergesort(int l,int r)//歸併排序求逆序數 { if(l>=r) return; int mid=(l+r)>>1; mergesort(l,mid); mergesort(mid+1,r); int st=l,mt=mid+1,k=l; while(st<=mid && mt<=r) { if(tmp[st]<=tmp[mt]) use[k++]=tmp[st++]; else use[k++]=tmp[mt++],antinum+=mid-st+1; } while(st<=mid) use[k++]=tmp[st++]; while(mt<=r) use[k++]=tmp[mt++]; while(l<=r) tmp[l]=use[l],l++; } void up(int n,int x) { while(n<=M) { sum[n]+=x; n+=lowbit(n); } } int getsum(int n) { int res=0; while(n>0) { res+=sum[n]; n-=lowbit(n); } return res; } int main() { srand( time(NULL) ); antinum=0; memset(vis,0,sizeof(vis)); for(int i=1;i<=M;i++) { int x=rand()%M+1; if(vis[x]) {i--;continue;} vis[x]=1; num[i]=x,tmp[i]=x; cout<<x<<endl; } int antimax=0; for(int i=1;i<=M;i++)//樹狀陣列求一個數的最大逆序數對 { antimax=max(antimax,i-getsum(num[i]-1)); up(num[i],1); } mergesort(1,M); int m=antimax*(2*M-1-antimax)/2; int u=0,v=0; for(int i=1;i<M;i++) { int tag=1; for(int j=1;j<M-i+1;j++,v++) if(num[j]>num[j+1]) u++,swap(num[j],num[j+1]),tag=0; if(tag) break; }//正常的冒泡,以便比較結果 冒泡寫錯好幾次 cout<<u<< " "<<v<<endl; cout<<antinum<<" "<< m<<endl; return 0; }