問題描述:html
輸入:n個數<a1,a2,...,an>。算法
輸出:輸入序列的一個排序(即從新排序)<a'1,a'2,...,a'n>,使得a'1≤a'2≤...≤a'n。數組
約定:數組A,下標從1開始測試
首先列出用到的數據來源程序(隨機產生1000個數)文件名:SortData.hspa
#include<stdio.h> #include<stdlib.h> #define RAND_NUM 10000 int *randData; void getRandData() { int i=0; randData=(int*)malloc(RAND_NUM*sizeof(int)); for ( i = 0; i < RAND_NUM; i++) randData[i]=1+(int)(RAND_NUM*1.0*rand()/(RAND_MAX+1.0)); } void printRandData() { int i=0; for ( i = 0; i < RAND_NUM; i++) { if(i%15==0) printf("\n"); printf("%5d",randData[i]); } printf("\n"); }
測試程序以下:其中紅色XXX.h爲不一樣的排序程序,替換後便可直接測試
#include<stdio.h> #include<stdlib.h> #include<time.h> #include"SortData.h" #include"XXX.h" int main() { clock_t start,finish; double duration; int wait; printf("Before Sort:"); getRandData(); printRandData(); start=clock(); XXX(randData,RAND_NUM); finish=clock(); printf("After Sort:"); printRandData(); duration = (double)(finish - start) / CLOCKS_PER_SEC; printf( "Sort Used time:%f seconds\n", duration ); scanf("%d",&wait); }
1.冒泡排序3d
算法思想: 將被排序的記錄數組A[1..n]垂直排列,每一個記錄A[i]看做是重量爲A[i]的氣泡。根據輕氣泡不能在重氣泡之下的原則,從下往上掃描數組R:凡掃描到違反本原則的輕氣泡,就使其向上"飄浮"。如此反覆進行,直到最後任何兩個氣泡都是輕者在上,重者在下爲止。code
算法僞代碼以下:htm
1 BUBBLE_SORT(A) 2 i <- length(A) 3 for i downto 1 4 j=1 5 while j<i 6 if(A[j+1]<A[j]) 7 A[j+1]<->A[j]
8 j++
舉例說明:數組A{5,1,3,9,2},冒泡排序執行過程以下:blog
如上圖所示,A4,A5,數組A已經排好了,因此不須要移動數組元素。排序
冒泡排序源代碼以下,BubbleSort.h
#include<stdio.h> /* 冒泡排序: 數組a,須要排序數組 length爲數組長度 */ void BubbleSort(int *a,int length) { int flage=0; int i=length-1; int j; int swap; for (; i >-1; i--) { if(flage==1) break; j=0; while(j<i) {flage=1; if(a[j+1]<a[j]) { swap=a[j]; a[j]=a[j+1]; a[j+1]=swap; flage=0; } j++; } } }
運行結果以下圖:
2.插入排序
算法思想:相似於打牌的過程,手中的牌表明已經排好序的數組,而桌子上的牌表明未排序的數組。
算法僞代碼以下:
INSERT_SORT(A) j<-2 while j<=length(A) do key<-A[j] i=j-1 while(i>0 and A[i]>key) do A[i+1]<-A[i] i<-i-1 A[i+1]<-key
舉例說明:數組A{5,1,3,9,2},插入排序執行過程以下:
插入排序源代碼以下:
#include<stdio.h> /* 插入排序: 數組a:待排序數組 length:數組長度 */ void InsertSort(int a[],int length) { int key; int j; if(length<=0) return ; for (int i = 1; i < length; i++) { key=a[i]; j=i-1; while(j>=0&&a[j]>key) { a[j+1]=a[j]; j--; } a[j+1]=key; } }
運行結果以下:
3.選擇排序
算法思想:首先找出A中最小的元素,並將其他A[1]中的的元素交換。接着,找出A中的次小最小元素,並將其與A[2]中的元素互換。對A中頭n-1個元素繼續這一過程。
僞代碼以下:
SELECT_SORT(A) for j<-2 to length[A] min=A[j-1] i=j while i<=length[A] if A[i]<min min=A[i] i++ A[i]<->A[j-1]
舉例說明:數組A{5,1,3,9,2},選擇排序執行過程以下:
上圖省略了找最小值的過程。
選擇排序源代碼以下:
#include<stdio.h> /* 選擇排序: 數組a:待排序數組 length:數組長度 */ void SelectionSort(int a[],int length) { int i,j,min,swap,index; for ( i = 1; i < length; i++) { min=a[i-1]; j=i; index=i-1; while (j<length) { if(a[j]<min) { min=a[j]; index=j; } j++; } if(index!=i-1){ swap=a[i-1]; a[i-1]=min; a[index]=swap; } } }
運行結果以下圖所示:
4.合併排序
算法思想:分解:將n個元素分紅各含n/2個元素的子序列。解決:用合併排序法對兩個字序列遞歸地排序;合併:合併兩個已排序的子序列以獲得排序結果。
算法僞代碼以下:
MERGE_SORT(A,p,r) if p<r q=(p+r)/2 MERGE_SORT(A,p,q) MERGE_SORT(A,q+1,r) MERGE(A,p,q,r) MERGE(A,p,q,r) n1 <- q-p+1 n2 <- r-q create array L[1..n1+1] and R[1...n2+1] for i<- 1 to n1 L[i]<-A[p+i-1] for j<- 1 to n2 R[j]<- A[q+j] L[n1+1]=∞ R[n2+1]=∞ i<-1 j<-1 for k <- p to r do if L[i]≤R[j] then A[k]<-L[i] i<-i+1 else A[k]<R[j] j<- j+1
舉例說明:數組A{5,1,3,9,2},合併排序執行過程以下:
上圖中,向下的箭頭表示分治的過程,向上的箭頭表示合併的過程。
合併排序源代碼以下所示:
#include<stdio.h> #include<stdlib.h> void Merge(int a[],int p,int q, int r) { int ln=q-p+1; int rn=r-q; int k=p,i,j; int *L=(int *)calloc(ln,sizeof(int)); int *R=(int *)calloc(rn,sizeof(int)); if(!L||!R) { printf("calloc Error!"); return ; } for (i = 0; i < ln; i++) *(L+i)=a[p+i]; for (j = 0; j < rn; j++) *(R+j)=a[q+1+j]; i=p; j=q+1; while(k<=r) { if(i==q+1) { while(j<=r&&k<=r) { a[k++]=*(R+j-q-1); j++; } } else if(j==r+1) { while(i<=q&&k<=r) { a[k++]=*(L+i-p); i++; } } else if(*(R+j-q-1)>*(L+i-p)) { a[k++]=*(L+i-p); i++; } else { a[k++]=*(R+j-q-1); j++; } } } void MergeSort(int a[],int p,int r) { if(p>=r) return; int q=(p+r)/2; MergeSort(a,p,q); MergeSort(a,q+1,r); Merge(a,p,q,r); }
運行結果以下圖所示:
5.堆排序
我之前寫過一篇關於堆排序的博客,這是地址http://www.cnblogs.com/lufangtao/archive/2012/06/04/2535268.html
這是給出源代碼和運行結果:
#include<stdio.h> #include<stdlib.h> int heap_size=0; int array_length=0; /* 返回結點i的左結點 */ int LEFT(int i) { return 2*i; } /* 返回結點i的右結點 */ int RIGHT(int i) { return 2*i+1; } /* 返回結點i的父節點 */ int PARENT(int i) { return i/2; } /* 保持最大堆性質 LEFT(i)和RIGHT(i)爲最大堆 */ void MAX_HEAPIFY(int a[],int i) { int r=RIGHT(i); int l=LEFT(i); int largest=-1; int temp; if((l<=heap_size)&&(a[l]>a[i])) largest=l; else largest=i; if((r<=heap_size)&&(a[r]>a[largest])) largest=r; if(largest!=-1&&largest!=i) { temp=a[largest]; a[largest]=a[i]; a[i]=temp; MAX_HEAPIFY(a,largest); } } /* 對數組a,創建最大堆 */ void BUILD_MAX_HEAP(int a[]) { heap_size=array_length; for (int i = heap_size/2; i >= 0; i--) MAX_HEAPIFY(a,i); } /* 堆排序 */ void HEAPSORT(int a[],int length) { int temp; array_length=length; BUILD_MAX_HEAP(a); for (int i = array_length; i >0; i--) { temp=a[0]; a[0]=a[heap_size]; a[heap_size]=temp; heap_size--; MAX_HEAPIFY(a,0); } }
運行結果以下圖所示:
6.快速排序
算法思想:
分解:數組A[p..r]被劃分紅兩個(可能爲空)子數組A[p..q-1]和A[q+1,r],使得A[p..q-1]中的每一個元素都小於A[q],並且小於等於A[q+1,..r]中的元素。下標也在這個劃分過程當中計算。
解決:經過遞歸調用快速排序,對數組A[p..q-1]和A[q+1..r]排序。
合併:由於兩個子數組是就地排序的,將它們的合併不須要操做,整個數組A[p..r]已經排序。
快速排序僞代碼以下:
QUICK_SORT(A,p,r) if p<r q=PARTITION (A,p,r) QUICK_SORT(A,p,q-1) QUICK_SORT(Q,q+1,r) PARTITION(A,p,r) x <- A[r] i <- p-1 for j <- p to r-1 if A[j]≤x then i <- i+1 exchange A[i] <-> A[j] exchange A[i+1] <-> A[r] return i+1
舉例說明:數組A{5,1,3,9,2},快速排序執行過程以下:
程序源代碼以下:
#include<stdio.h> /* 對數組a[p...r]進行劃分,返回劃分的位置 */ int PARTITION(int a[],int p,int r) { int key=a[r]; int i=p-1; int temp; for (int j = p; j < r; j++) if(a[j]<=key) { temp=a[j]; a[j]=a[++i]; a[i]=temp; } temp=a[i+1]; a[i+1]=a[r]; a[r]=temp; return i+1; } /* 對數組a[p...r]進行快速排序 */ void QUICKSORT(int a[],int p,int r) { if(p>=r) return ; int q=PARTITION(a,p,r); QUICKSORT(a,p,q-1); QUICKSORT(a,q+1,r); }
測試結果以下圖所示:
7.希爾排序
算法思想:將整個待排序元素序列分割成若干個子序列(由相隔某個「增量」的元素組成的)分別進行直接插入排序,而後依次縮減增量再進行排序,待整個序列中的元素基本有序(增量足夠小)時,再對全體元素進行一次直接插入排序。由於直接插入排序在元素基本有序的狀況下(接近最好狀況),效率是很高的。
舉例說明:數組A{1,55,3,9,2},希爾排序執行過程以下:
第一次 gap = 5/2=2 即 1,3,2一組,5,9一組
第二次 gap= 2/2=1 即 對整個數組進行插入排序
第三重 gap=1/2=0,必需要進行排序
希爾排序源代碼以下:
1 #include<stdio.h> 2 /* 3 希爾排序 4 數組a:待排序的數組 5 length:數組長度 6 */ 7 void ShellSort(int a[],int length) 8 { 9 int gap=length/2;//初始步長爲數組長度的通常 10 int j,i,key,swap,k; 11 for (;gap>0;gap/=2) 12 { 13 for (i= 0; i < gap; i++) 14 { 15 for(j=i+gap;j<length;j+=gap) 16 { 17 if(a[j]<a[j-gap]) 18 { 19 key=a[j]; 20 k=j-gap; 21 while(k>=0&&a[k]>key) 22 { 23 a[k+gap]=a[k]; 24 k-=gap; 25 } 26 a[k+gap]=key; 27 } 28 } 29 } 30 } 31 }
運行結果以下圖所示:
8.計數排序
算法思想:n個輸入元素中的每一個都是介於0到k之間的整數
僞代碼以下:
1 COUNT-SORT(A) 2 for i<- 0 to k 3 C[i] <- 0 4 for j<-1 to length[A] 5 C[A[j]] <-C[A[j]]+1 6 for i<- 1 to k 7 C[i] <- C[i-1]+C[i] 8 for j<-length[A] downto 1 9 do B[C[A[j]]] <- A[j] 10 C[A[j]] <- C[A[j]]-1 11
舉例說明:數組A{5,1,3,9,2},計數排序執行過程以下:
計數排序代碼以下:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include"SortData.h" 4 void CountSort(int a[],int length) 5 { 6 int *C=(int*)malloc(RAND_NUM*sizeof(int));; 7 int *b=(int*)malloc(length*sizeof(int));; 8 int i,j,k; 9 for ( i = 0; i < RAND_NUM+1; i++) 10 C[i]=0; 11 for (j = 0; j < length; j++) 12 C[a[j]]++; 13 for ( i = 1; i < RAND_NUM+1; i++) 14 C[i]=C[i]+C[i-1]; 15 for (k= length-1; k>-1 ; k--) 16 { 17 b[C[a[k]]]=a[k]; 18 C[a[k]]--; 19 } 20 for ( k = 0; k < length; k++) 21 a[k]=b[k]; 22 }
運行結果以下圖所示: