标签:
内部排序算法总结:
排序算法有各自的时间复杂度,并不代表时间复杂度高的算法在任何情况下就比时间复杂度低的算法要低效,相反也一样。排序算法按照其最基本的操作可以分为以下几种类型:
1 /** 2 简单插入排序 3 */ 4 void Sort::InsertSort(int* array,int size){ 5 int i,j,x; 6 for(i=1;i<size;i++){ 7 if(array[i]<array[i-1]){ //前i-1个元素有序,若array[i]>= array[i-1],则有序,直接后移, 8 j = i-1; //若array[i]<array[i-1],往前插入至合适位置 9 x = array[i]; 10 while(x<array[j]){ 11 array[j+1] = array[j]; 12 j--; 13 } 14 array[j+1] = x; 15 } 16 } 17 }
将未排序的元素中依次插入到已经排好序的有序表中,因为是插入到有序表中,可以通过折半查找的方式先找到要插入的位置。
1 /* 2 返回位置i,使得将x插入i后变得有序 3 */ 4 int BinarySearch(int *array, int size, int x){ 5 if(size == 0) return 0; 6 if( x<array[0]) return 0; 7 int half = size/2; 8 if( x < array[half]) 9 return BinarySearch(array,half-1,x); 10 else{ 11 return half+BinarySearch(array+half+1,size-half-1,x)+1; 12 } 13 } 14 /** 15 折半插入 16 */ 17 void Sort::BinaryInsertSort(int* array, int size){ 18 int i,j,x,p; 19 for(i=1;i<size-1;i++){ 20 if(array[i]<array[i-1]){ //前i-1个元素有序,若array[i]>= array[i-1],则有序,直接后移, 21 x = array[i]; //若array[i]<array[i-1],往前插入至合适位置 22 j = BinarySearch(array,size,x); 23 p = i; 24 while(p>j){ 25 array[p] = array[p-1]; 26 } 27 array[j] = x; 29 } 30 } 31 }
将未排序的元素中依次插入到已经排好序的有序表中,因为是插入到有序表中,可以通过折半查找的方式先找到要插入的位置。
1 void ShellGroupSort(int *array, int size, int step){ 2 int i,j,x; 3 for(i=step;i<size;i++){ 4 if(array[i] < array[i-step]){ 5 x= array[i]; 6 j = i-step; 7 while(x<array[j]){ 8 array[j+step] = array[j]; 9 j-= step; 10 } 11 array[j+step] = x; 12 } 13 } 14 } 15 void Sort::ShellSort(int*array, int size){ 16 int i = size/2; 17 while(i>0){ 18 ShellGroupSort(array,size,i); 19 i = i/2; 20 } 21 }
在要排序的一组数中,选出最小(或者最大)的个数与第1个位置的数交换;然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后个数)比较为止
void Sort::SelectSort(int *array, int size){ int i=0,j; for(;i<size-1;i++){ int minIndex = i; for(j=i;j<size;j++){ //寻找最小元素下标 if(array[j]<array[minIndex]) minIndex = j; } int temp = array[minIndex]; array[minIndex] = array[i]; array[i] = temp; } }
堆可以被看做是一棵完全二叉树,若该二叉树中非叶子节点的值不大于其后代节点得值,我们称之为小堆,若非叶子节点的值不小于其后代节点值,称之为大堆,而堆排序就是每次选择堆顶元素,即该堆的最大或者最小元素,将其与堆尾元素置换(堆顶元素置换后将不作为堆的元素,即不参与后面堆得调整),并调重新调整被破坏了堆,直到堆中只剩一个元素。
因此,除了第一次建立堆的过程,堆排序的过程就是不断调整堆得过程,那么如何调整一个被破坏了堆呢?
调整堆
当第一个元素与堆尾元素置换后, 除了堆顶元素没有堆的性质外,其他的堆元素都保持着堆得性质,因此只要将堆顶元素沿着其后代节点,调整到相应位置即可,具体操作如下(以小堆为例):
选择堆顶元素,与较小的后代节点置换,并递归该过程直至满足小堆性质
建堆
不难看出,堆的另一个性质是,堆得任意子树也是堆,因此建堆的过程就是把其所有的子树调整为堆的过程,我们可以从以非叶子节点为根的子树开始(因为以叶子节点根节点的子树已经是一个完整的堆),从后往前依次调整
1 /* 2 调整堆,只有堆顶元素不满足堆的性质 3 */ 4 void AdjustHeap(int *array,int size, int root){ 5 if(root >= size/2) return; 6 int leftIndex = (root+1)*2-1; 7 int minIndex = leftIndex; 8 int rightIndex = (root+1)*2; 9 //倘若其存在右孩子,并且右孩子比左孩子还小 10 if(rightIndex < size && array[minIndex] > array[rightIndex]) minIndex = rightIndex; 11 12 if(array[root] <= array[minIndex]) 13 return; 14 else{ 15 int temp = array[root]; 16 array[root] = array[minIndex]; 17 array[minIndex] = temp; 18 AdjustStack(array,size,minIndex); 19 } 20 } 21 /* 22 建立堆的过程 23 */ 24 void BuildHeap(int *array,int size){ 25 int root = size/2-1; 26 while(root>0){ 27 AdjustHeap(array,size,root); 28 root--; 29 } 30 } 31 void Sort::HeapSort(int *array, int size){ 32 BuildHeap(array,size); 33 while(size>1){ 34 int temp = array[size-1]; 35 array[size-1] = array[0]; 36 array[0] = temp; 37 38 AdjustHeap(array,size,0); 39 size--; 40 } 41 }
在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒。即:每当两相邻的数比较后发现它们的排序与排序要求相反时,就将它们互换。
标签:
原文地址:http://www.cnblogs.com/chenhaibin/p/4662018.html