#include
#include
【資料圖】
#include
#include
#include
#include
using namespace std;
// a和b數(shù)值進(jìn)行交換
Swap(int& a,int& b){
if (a==b)return;
int k=a;
a=b;
b=k;
}
/*******************************1、冒泡排序****************************/
//原理:依次比較相鄰的2個(gè)數(shù),將比較小的數(shù)放在前面,比較大的數(shù)放在后面
BubbleSort(int arrNum[], int nSize){
int i=0;
int j=0;
int n=nSize;//數(shù)組含有元素的個(gè)數(shù)
//如果數(shù)組個(gè)數(shù)少于2個(gè),沒有必要比較,直接退出
if(n<=1)return;
for (i=0;i //n-i-1是每輪比較的最大次數(shù);因?yàn)橄聵?biāo)j+1要小于數(shù)組的最大下標(biāo),所以還要-1 for (j=0;j Swap(arrNum[j],arrNum[j+1]); } } } /**************************2、選擇排序******************************/ //原理:每次從待排序的數(shù)據(jù)元素中選出最小(或者最大)的一個(gè)元素,存放在已排好序列的起始位置(或者末尾位置), 直到全部待排序 SelectionSort(int arrNum[],int nSize){ int i=0; int j=0; int n=nSize; if (n<=1)return; for (i=0;i int pos=i;//pos記錄值最小的數(shù)組下標(biāo)位置 for (j=i;j if (arrNum[pos]>arrNum[j]) pos=j; } Swap(arrNum[i],arrNum[pos]); } } /*********************3、直接插入排序******************************/ //原理:是將無(wú)序序列中的數(shù)據(jù)插入到有序的序列中,在遍歷無(wú)序序列時(shí),首先拿無(wú)序序列中的首元素去與有序序列中的每一個(gè)元素比較并插入到合適的位置,一直到無(wú)序序列中的所有元素插完為止。 InsertionSort(int arrNum[], int nSize){ int i=0; int j=0; int n=nSize; if (n<=1)return; for (i=0;i for (j=i+1;j Swap(arrNum[i],arrNum[j]); } } } /***********************************4、希爾排序***********************/ //原理:是把序列按下標(biāo)的一定增量分組,對(duì)每組使用直接插入排序算法排序;隨著增量的逐漸減少,每組包含的關(guān)鍵詞越來(lái)越多,當(dāng)增量減至1時(shí),整個(gè)序列恰好被分為一組,算法便終止。 //分組增量gap=length/2,縮小增量以gap=gap/2 ShellSort(int arrNum[], int nSize){ int j=0; int i=0; int n=nSize; int gap=n/2; if (n<=1 || gap<1)return; while (gap>0){ for (i=0;i for (j=i+gap;j Swap(arrNum[i],arrNum[j]); } } gap=gap/2; } } /****************************5、歸并排序******************************/ //原理算法:先把數(shù)據(jù)組分成一半,再把左邊的數(shù)組再分一半排序,右邊的數(shù)組再分一半,一直分到只有2個(gè)有序數(shù)為至,然后再歸并 MergeSort(int arrNum[], int low,int high){ int i=0; int j=0; int k=0; int n=0; int half=low+(high-low)/2; //不能再分的條件,high是當(dāng)前數(shù)組的個(gè)數(shù),不是最大元素的下標(biāo) if (low>=(high-1))return; //先分 MergeSort(arrNum,low,half); MergeSort(arrNum,half,high); //再合 //臨時(shí)開辟動(dòng)態(tài)數(shù)組 n=high-low; int* pArray=(int*)malloc(n*sizeof(int)); memset(pArray,0,n*sizeof(int)); i=0; j=low; k=half; while(j if (arrNum[j]>arrNum[k]) pArray[i++]=arrNum[k++]; else pArray[i++]=arrNum[j++]; } while(j pArray[i++]=arrNum[j++]; while(k pArray[i++]=arrNum[k++]; for (i=0;i arrNum[low++]=pArray[i]; free(pArray); } /*********************6、快速排序*******************************/ //選擇一個(gè)基準(zhǔn)數(shù),通過(guò)一趟排序?qū)⒁判虻臄?shù)據(jù)分割成獨(dú)立的兩部分;其中一部分的所有數(shù)據(jù)都比另外一部分的所有數(shù)據(jù)都要小。 //然后,再按此方法對(duì)這兩部分?jǐn)?shù)據(jù)分別進(jìn)行快速排序,整個(gè)排序過(guò)程可以遞歸進(jìn)行,以此達(dá)到整個(gè)數(shù)據(jù)變成有序序列。 QuickSort(int arrNum[], int low,int high){ int i=low; int j=high-1; int nBase=arrNum[low]; //遞歸中止條件 if (i>=j)return; //基準(zhǔn)數(shù)選取當(dāng)前數(shù)組區(qū)間的第1個(gè)元素 while(true){ //從后向前掃描,找小于基準(zhǔn)數(shù)的值,然后放到下標(biāo)為i的位置 while(i if(nBase<=arrNum[j]) j--; else{ arrNum[i]=arrNum[j]; break; } } //從前向后掃描,找大于基準(zhǔn)數(shù)的值,然后放到下標(biāo)為j的位置 while(i if(nBase>arrNum[i]) i++; else{ arrNum[j]=arrNum[i]; break; } } if (i==j){ arrNum[i++]=nBase; break; } } QuickSort(arrNum,low,i); QuickSort(arrNum,i,high); } //建立大堆 //堆是一種非線性結(jié)構(gòu),可以把堆看作一個(gè)數(shù)組,也可以被看作一個(gè)完全二叉樹,通俗來(lái)講堆其實(shí)就是利用完全二叉樹的結(jié)構(gòu)來(lái)維護(hù)的一維數(shù)組但堆并不一定是完全二叉樹 //按照堆的特點(diǎn)可以把堆分為大頂堆和小頂堆 //大頂堆:每個(gè)結(jié)點(diǎn)的值都大于或等于其左右孩子結(jié)點(diǎn)的值 //小頂堆:每個(gè)結(jié)點(diǎn)的值都小于或等于其左右孩子結(jié)點(diǎn)的值 //二叉數(shù),設(shè)深度為h(根節(jié)點(diǎn)層數(shù)為0),某個(gè)父節(jié)點(diǎn)為dad,子節(jié)點(diǎn)為son,有以下特點(diǎn): //滿二叉數(shù): 總節(jié)點(diǎn)數(shù)是:2^(h+1)-1,第k層節(jié)點(diǎn)數(shù)是:2^k //完全二叉數(shù):第k層節(jié)點(diǎn)數(shù)是:2^k //父和子節(jié)點(diǎn)的2個(gè)元素序號(hào)關(guān)系:dad=son*2+1,dad=son*2+2 MaxHeap(int arrNum[], int start,int tail){ int dad=0; //存放父節(jié)點(diǎn)序號(hào) int son=0; //存放子節(jié)點(diǎn)序號(hào) dad=start; son=dad*2+1;//左孩子節(jié)點(diǎn) //當(dāng)有孩子節(jié)點(diǎn)時(shí) while(son<=tail){ //當(dāng)同時(shí)存在2個(gè)子節(jié)點(diǎn)時(shí),先比較2個(gè)子節(jié)點(diǎn)值的大小,選擇值最大的節(jié)點(diǎn) if (son+1<=tail){ if (arrNum[son] son=son+1; } //如果父節(jié)點(diǎn)的值大于子節(jié)點(diǎn)(最大值的子節(jié)點(diǎn))時(shí),直接返回 if (arrNum[dad]>arrNum[son])return; //如果父節(jié)點(diǎn)的值小于子節(jié)點(diǎn)的值時(shí),交換位置 Swap(arrNum[dad],arrNum[son]); //使當(dāng)前子節(jié)點(diǎn)成為父節(jié)點(diǎn),往下繼續(xù)查找比較建立大堆 dad=son; son=dad*2+1; } } /*************************7、堆排序**********************************/ //原理:堆排序是利用堆這種數(shù)據(jù)結(jié)構(gòu)而設(shè)計(jì)的一種排序算法,堆排序是一種選擇排序,它的最壞,最好,平均時(shí)間復(fù)雜度均為O(nlogn),它也是不穩(wěn)定排序,首先簡(jiǎn)單了解下堆結(jié)構(gòu) HeapSort(int arrNum[], int nSize){ int i=0; int j=0; int k=0; //初始化構(gòu)建一個(gè)完全二叉數(shù),方法是:(length/2-1)為最后一個(gè)父節(jié)點(diǎn),從當(dāng)前父節(jié)點(diǎn)往下構(gòu)建大堆,然后循環(huán)一直到根節(jié)點(diǎn) i=nSize/2-1; for (i;i>=0;i--) MaxHeap(arrNum,i,nSize-1); //從最后一個(gè)元素開始向上查找,將第一個(gè)元素和已經(jīng)排好的元素前一位交換, //再重新調(diào)整,構(gòu)建小堆,直到排序完畢 for (i=nSize-1;i>0;i--) { Swap(arrNum[0],arrNum[i]); MaxHeap(arrNum,0,i-1); } } /*************************8、計(jì)數(shù)排序*****************************/ //一步:找出原數(shù)組中元素值最大的,記為max。 //第二步:創(chuàng)建一個(gè)新數(shù)組count,其長(zhǎng)度是max加1,其元素默認(rèn)值都為0。 //第三步:遍歷原數(shù)組中的元素,以原數(shù)組中的元素作為count數(shù)組的索引,以原數(shù)組中的元素出現(xiàn)次數(shù)作為count數(shù)組的元素值。 //第四步:創(chuàng)建結(jié)果數(shù)組result,起始索引index。 //第五步:遍歷count數(shù)組,找出其中元素值大于0的元素,將其對(duì)應(yīng)的索引作為元素值填充到result數(shù)組中去,每處理一次,count中的該元素值減1,直到該元素值不大于0,依次處理count中剩下的元素。 //第六步: 返回結(jié)果數(shù)組result? CountSort(int arrNum[], int nSize){ int i=0; int j=0; int min=0; int max=0; int n=0; int* pArray=NULL; min=arrNum[0]; max=min; for (i=1;i if(min>arrNum[i]) min=arrNum[i]; if(max max=arrNum[i]; } n=max-min+1; //準(zhǔn)備開辟的動(dòng)態(tài)數(shù)組的空間 pArray=new int[n];//申請(qǐng)動(dòng)態(tài)數(shù)組 memset(pArray,0,sizeof(arrNum[0])*n); //計(jì)數(shù)排序第1種計(jì)算方法 // for (i=0;i // pArray[arrNum[i]-min]++; // for (j=0,i=0;i // { // while (pArray[i]-->0) // arrNum[j++]=i+min; // } //計(jì)數(shù)排序第2種計(jì)算方法 //需要在創(chuàng)建一個(gè)臨時(shí)數(shù)組,和原數(shù)組大小一樣 int* pArrayTemp=new int[nSize]; //哪個(gè)位置有值,標(biāo)記為1,如果有多個(gè)值,每次+1 for (i=0;i pArray[arrNum[i]-min]++; //構(gòu)建計(jì)數(shù)數(shù)組 for (i=1;i pArray[i]+=pArray[i-1]; //把排序的結(jié)果數(shù)據(jù)臨時(shí)存放到臨時(shí)數(shù)組pArraytemp中 for (i=0;i //作為pArray的下標(biāo)[arrNum[i]-min] int index=arrNum[i]-min; pArrayTemp[pArray[index]-1]=arrNum[i]; pArray[index]--; } for (i=0;i arrNum[i]=pArrayTemp[i]; delete[] pArrayTemp; pArrayTemp=NULL; delete[] pArray;//釋放動(dòng)態(tài)數(shù)組空間 pArray=NULL; } /***************************9、桶排序**********************************/ //原理:桶排序是計(jì)數(shù)排序的擴(kuò)展版本,計(jì)數(shù)排序可以看成每個(gè)桶只存儲(chǔ)相同元素,而桶排序每個(gè)桶存儲(chǔ)一定范圍的元素,通過(guò)映射函數(shù),將待排序數(shù)組中的元素映射到各個(gè)對(duì)應(yīng)的桶中, //對(duì)每個(gè)桶中的元素進(jìn)行排序,最后將非空桶中的元素逐個(gè)放入原序列中。 BucketSort(int arrNum[], int nSize){ int i=0; int j=0; int n=0; //記錄桶的個(gè)數(shù) int max=arrNum[0]; int min=arrNum[0]; //確認(rèn)桶的個(gè)數(shù),公式: (最大值-最小值)/數(shù)組長(zhǎng)度 for (i=1;i if (arrNum[i] min=arrNum[i]; if (arrNum[i]>max) max=arrNum[i]; } n=(max-min)/nSize+1; //桶的個(gè)數(shù) vector for(i=0;i vector pVector[i]=v; } for(i=0;i int index=(arrNum[i]-min)/nSize; pVector[index].push_back(arrNum[i]); } for(i=0;i if (pVector[i].size()>0) sort(pVector[i].begin(),pVector[i].end()); } for (j=0,i=0;i if(pVector[i].size()>0){ vector for(it;it!=pVector[i].end();++it){ arrNum[j++]=*it; } } } delete[] pVector; pVector=NULL; } /***************************10、基數(shù)排序*************************/ //它是這樣實(shí)現(xiàn)的:將所有待比較數(shù)值(正整數(shù))統(tǒng)一為同樣的數(shù)位長(zhǎng)度,數(shù)位較短的數(shù)前面補(bǔ)零。然后,從最低位開始,依次進(jìn)行一次排序。這樣從最低位排序一直到最高位排序完成以后, 數(shù)列就變成一個(gè)有序序列。 RadixSort(int arrNum[], int nSize){ int i=0; int j=0; int n=0;//記錄循環(huán)次數(shù) int arrCount[10]={0}; //記錄每個(gè)數(shù)當(dāng)前位的數(shù)字的數(shù)組 int nRadix=0; int* pArray=NULL; //獲取數(shù)組中最大的數(shù)值 for (i=0;i n=(arrNum[i]>n)?arrNum[i]:n; //獲取最大數(shù)的位數(shù) i=n,n=0; while(i>0){ i=i/10; n++; } pArray=new int[nSize]; i=0,nRadix=1; while(i for (j=0;j int index=(arrNum[j]/nRadix)%10;//獲取當(dāng)前位的數(shù)字 arrCount[index]++; } for (j=1;j<10;j++){ arrCount[j]+=arrCount[j-1]; } memset(pArray,0,sizeof(int)*nSize); for (j=nSize-1;j>=0;j--){ int index=(arrNum[j]/nRadix)%10;//獲取當(dāng)前位的數(shù)字 pArray[arrCount[index]-1]=arrNum[j]; arrCount[index]--; } for (j=0;j arrNum[j]=pArray[j]; } memset(arrCount,0,40); nRadix=nRadix*10; i++; } delete[] pArray; }
標(biāo)簽: 動(dòng)態(tài)數(shù)組 完全二叉樹