一、氣泡排序
時間複雜度:O(N²)
原理:從陣列的第一個位置開始兩兩比較array[index]和array[index+1],如果array[index]大於array[index+1]則交換array[index]和array[index+1]的位置,直到陣列結束。
void Bubble(int array[], int size) { int i,j; for(i=0; i<size; i++) { for(j=i+1; j<size; j++) { if(array[i]>array[j]) { array[i]=array[i]^array[j]; array[j]=array[i]^array[j]; array[i]=array[j]^array[i]; } } }
二、選擇排序
時間複雜度:O(N^2),與氣泡排序相比減少了陣列交換的次數
原理:選擇一個 array[0]作為標杆,然後迴圈找到除這個外最小的 (查詢小於標杆的最小 ),交換這兩個,這時最小就被放到了array[0]上,然後再將array[1]作為標杆,從剩下未排序的 中找到最小 ,並交換。
void Sort(int array[], int size) { int i,j,k; for(i=0; i<size; i++) { k=i; for(j=i+1; j<size; j++) { if(array[j]<array[k]) { k=j; } } if(i!=k) { array[i]=array[i]^array[k]; array[k]=array[k]^array[i]; array[i]=array[i]^array[k]; } } }
三、插入排序
時間複雜度:插入排序對隨即順序的序列的時間複雜度也為O(N^2),但是對於基本有序的序列進行排序時間複雜度為O(N)
適用:一般不用在資料大於1000的場合或者重複排序超過200資料項的序列使用插入排序
原理:插入排序的思想是陣列是部門有序的,然後將無序的部分迴圈插入到已有序的序列中。
void InsertSort(int array[], int size) { int i,j,temp; for(i=2; i<size; i++) { temp=array[i]; for(j=i-1; j>=0 && array[j]>temp; j--) { array[j+1]=array[j]; } array[j+1]=temp; } }
四、希爾排序/縮小增量排序
時間複雜度:n的1.2次冪
適用:適合於資料量在5000以下並且速度並不是特別重要的場合。
原理:先將整個待排元素序列分割成若干個子序列(由相隔某個“增量”的元素組成的)分別進行直接插入排序,然後依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。因為直接插入排序在元素基本有序的情況下(接近最好情況),效率是很高的,因此希爾排序在時間效率上比前兩種方法有較大提高。
void shellSort(int array[], int size) { int i,j,temp; int increment=size; do { increment=increment/3+1; for(i=increment+1; i<size; i++) { temp=array[i]; for(j=i-increment; j>=0 && array[j]>temp; j-=increment) { array[j+increment]=array[j]; } array[j+increment]=temp; } }while(increment>1); }
五、堆排序
時間複雜度:O(N*logN)
適用:適合於資料量非常大的場合(百萬資料)
原理:利用大頂堆(小頂堆)堆頂記錄的是最大關鍵字(最小關鍵字)這一特性,使得每次從無序中選擇最大記錄(最小記錄)變得簡單。
其基本思想為(大頂堆):
1)將初始待排序關鍵字序列(R1,R2....Rn)構建成大頂堆,此堆為初始的無須區;
2)將堆頂元素R[1]與最後一個元素R[n]交換,此時得到新的無序區(R1,R2,......Rn-1)和新的有序區(Rn),且滿足R[1,2...n-1]<=R[n];
3)由於交換後新的堆頂R[1]可能違反堆的性質,因此需要對當前無序區(R1,R2,......Rn-1)調整為新堆,然後再次將R[1]與無序區最後一個元素交換,得到新的無序區(R1,R2....Rn-2)和新的有序區(Rn-1,Rn)。不斷重複此過程直到有序區的元素個數為n-1,則整個排序過程完成。
//array是待調整的堆陣列,i是待調整的陣列元素的位置,nlength是陣列的長度 //本函式功能是:根據陣列array構建大根堆 void HeapAdjust(int array[],int i,int nLength) { int nChild; int nTemp; for(;2*i+1<nLength;i=nChild) { //子結點的位置=2*(父結點位置)+1 nChild=2*i+1; //得到子結點中較大的結點 if(nChild<nLength-1&&array[nChild+1]>array[nChild])++nChild; //如果較大的子結點大於父結點那麼把較大的子結點往上移動,替換它的父結點 if(array[i]<array[nChild]) { nTemp=array[i]; array[i]=array[nChild]; array[nChild]=nTemp; } else break; //否則退出迴圈 } } //堆排序演算法 void HeapSort(int array[],int length) { int i; //調整序列的前半部分元素,調整完之後第一個元素是序列的最大的元素 //length/2-1是最後一個非葉節點,此處"/"為整除 for(i=length/2-1;i>=0;--i) HeapAdjust(array,i,length); //從最後一個元素開始對序列進行調整,不斷的縮小調整的範圍直到第一個元素 for(i=length-1;i>0;--i) { //把第一個元素和當前的最後一個元素交換, //保證當前的最後一個位置的元素都是在現在的這個序列之中最大的 array[i]=array[0]^array[i]; array[0]=array[0]^array[i]; array[i]=array[0]^array[i]; //不斷縮小調整heap的範圍,每一次調整完畢保證第一個元素是當前序列的最大值 HeapAdjust(array,0,i); } }