常用排序演算法以及時間複雜度
#include <iostream.h> #include <conio.h> #include <stdlib.h> #include <time.h> //折半插入排序 入口引數:long* Array:指向陣列的指標;long key:關鍵字;long Start:開始索引;long End:結束索引 int HalfSearch(long* Array,long Key,long Start,long End){ long half=(Start+End)/2; //找折半點 if(Array[half]<=Key && Array[half+1]>Key ) //找到了插入的位置 return half+1; if(Array[half]>Key) //折半點比關鍵字大,在左邊找 return HalfSearch(Array,Key,Start,half-1); else return HalfSearch(Array,Key,half+1,End); //在右邊找 } void HalfInsSort(long* array/*陣列*/,long leng/*陣列長度*/){ long temp; long i,j,Pos; for(i=2;i<=leng;i++){ temp=array[i];//從第二個數開始 j=i-1;//找到前一個數 if((temp<array[j]) && (j>=1)){//如果此處不是TEMP 的正確位置,則折半查詢 Pos=HalfSearch(array,temp,1,j); while(Pos<=j && Pos!=-1)//移動元素,騰出空間 {array[j+1]=array[j]; j--;} array[Pos]=temp;//放入適當的位置 } } } //希爾排序,引數解釋同上 void ShellSort(long* array,long leng){ int temp,step; step=leng/2;//以長度的1/2做為步長,也可以自己設定一個步長序列 while(step!=0){ for(int i=step+1;i<=leng;i++){//又i來控制迴圈 /*因為從最小步長前面開始排序,前面的 temp=array[i];//從步長數的第二個開始 /*已經有序了,所以象插入排序一樣,只是將後面的 int j=i-step;//找到了前一個的位置 /*小的數插入到前面適當的位置*/ while(temp<array[j] && j>=1){ array[j+step]=array[j];//大的數交換到後面,temp儲存小的數 j=j-step; } array[j+step]=temp;//小的數放到適當的位置 } step=step/2;//再找下一個步長 } } //二叉樹排序 //1.陣列表示 /*如果恰好此樹是一個從大到小的序列,則需要的樹空間為2的元素次方個儲存空間*/ /*空間的浪費太大,不划算*/ void BinaryTree(long* btree,/*排序的陣列*/long* array,/*原始陣列*/long leng/*陣列長度*/){ /*建樹的過程就是排序的過程*/ long i; long parent; btree[1]=array[1];/*頭接點賦值*/ for(i=2;i<=leng;i++){ parent=1; //確保每次的找插入節點都從ROOT開始 while(btree[parent]!=0){ if(array[i]>btree[parent]) //插入節點大於父節點,則作右孩子 parent=parent*2+1; else parent=parent*2; //插入節點小於父節點,則作左孩子 } btree[parent]=array[i]; //找到正確的位置後插入。返回開始處再找; } } void Inorder(long* btree,/*樹的頭接點*/long pos,/*找到的索引*/long leng/*陣列長*/){ //樹的中序遍歷*/ if(btree[pos]!=0 && pos<=leng){ //由於是陣列表示,所以加上此條件 Inorder(btree,pos*2,leng); //遍歷左孩子 if(btree[pos]!=0) cout<<btree[pos]<<" "; //列印節點 Inorder(btree,pos*2+1,leng);//遍歷右孩子 } } //2.連結串列表示 typedef struct Node{//基本資料結構 Node* left; long data; Node* right; }_Node; Node* CreateTree(long* array,/*給定的元素*/long leng/*長度*/){ long item; int leftflag; Node *root,*parent,*Left=NULL,*Right=NULL; root=new Node;/*建頭接點*/ root->data=array[1]; root->left=root->right=NULL; for(item=2;item<=leng;item++){ Node* newnode=new Node; //分配節點 newnode->data=array[item]; newnode->left=newnode->right=NULL; parent=root; while(parent!=NULL){ if(newnode->data<parent->data){//如果小於節點的值,到左子樹 if(parent->left==NULL) Left=parent; //左子樹為空,儲存父節點 parent=parent->left; leftflag=1;} else{ if(parent->right==NULL)//右子樹為空,儲存父節點 Right=parent; parent=parent->right; leftflag=0; } }; if(leftflag==1)//在左子樹 Left->left =newnode; else//在右子樹 Right->right =newnode; } if(root!=NULL) return root; else return NULL; } void Inorder(Node* root){//中序遍歷 if(root==NULL) return; Inorder(root->left); cout<<root->data<<" "; Inorder(root->right); } //交換排序 //1.氣泡排序 void BubbleSort(long* array,long leng){ long i,j; int finish=0; //是否交換的標誌,如果上一次有交換,此標誌為0,下一次 long temp; //可繼續比較,如果沒有交換,則表示排序完成,不須再比較。這是一個控制排序 //次數的小技巧,可減少排序的時間。 while(!finish){ finish=1; //假定已完成; for(j=leng;j>=1;j--){//控制次數 for(i=1;i<=j-1;i++){//交換的索引 if(array[i]>array[i+1]){ temp=array[i]; array[i]=array[i+1]; array[i+1]=temp; finish=0;//有交換,設定標誌位,以便上面的判斷 } } } } } //2.快速排序 //基本思想是找一個關鍵字,小於它的放在它的左邊,大於的放在右邊;對兩邊的序列繼續排 void QuickSort(long* array,long low,long high){ long key; long scanup,scandown; long temp; if((high-low)<=0) //設定第一個返回條件 return; if(high-low==1) //相臨的兩個數要比較是否要交換 if(array[high]>array[low]){//符合條件,交換 temp=array[high]; array[high]=array[low]; array[low]=temp; return; } key=array[low];//一般以最小索引的數做關鍵字 scanup=low; scandown=high; do{ while(array[scandown]>=key && scanup<scandown)//向前找到小於關鍵字的數 scandown--; array[scanup]=array[scandown]; //交換到前面 while(array[scanup]<=key && scanup<scandown)//向後找到大於關鍵字的數 scanup++; array[scandown]=array[scanup]; //交換到後面 }while(scandown!=scanup); //直到前後的掃描鍵在同一位置為關鍵字的地方 array[scanup]=key; QuickSort(array,low,scandown-1);//向前快排 QuickSort(array,scanup+1,high);//向後快排 } /*選擇排序*/ //1.直接選擇排序 void SelectSort(long* array,long leng){ long temp,k; long i,j; for(i=1;i<leng;i++){ k=i; //給臨時變數賦值; for(j=i+1;j<=lung s++) if(array[k]>=array[j]) k=j; //在此迴圈內找到當前最小值的下標 //只做一次交換; temp=array[k]; array[k]=array[i]; array[i]=temp; } } //2.堆排序 //基本思想:先由給出的關鍵字來建立一個堆,然後用 void CreateHeap(long* heap,/*陣列表示堆的指標*/long root/*頭接點的序號*/,long leng){//建堆 long child;//孩子接點 long temp; int finish=0; child=2*root; //找到子節點 temp=heap[root]; while(child<leng && finish==0){//在子接點的序號小於長度時或不需要交換時退出迴圈 if(child <leng) if(heap[child]<heap[child+1]) child++; //選出最大的子節點由於交換 if(temp >= heap[child]) //交換完成 finish=1; else{ heap[child/2]=heap[child]; //交換 child=2*child; //再找下層,直到不滿足迴圈的條件 } } heap[child/2]=temp; //節點放入適當的位置 } void HeapSort(long* heap,long leng){//排序 long i,temp; for(i=(leng/2);i>=1;i--) //建成大根堆 CreateHeap(heap,i,leng); for(i=leng;i>=1;i--){ //排序的方法是:由大根堆的最後一個開始,最後一個是大根堆裡關鍵值最小的一個,它和第一個數交換,將最大的數交換到最後,然後在對剩下的n-1個數進行建堆,重複此過程,使得大的數不斷放到後面,最後使整個序列有序。 temp=heap[i]; heap[i]=heap[1]; heap[1]=temp; CreateHeap(heap,1,i-1); //對餘下的部分建堆 } } 排序效率比較
|