算法学习之排序算法:选择排序

来源:互联网 发布:ubuntu 设置工作路径 编辑:程序博客网 时间:2024/06/09 07:43

选择排序:每一趟在n-i+1(i=1,2,...,n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。


一、简单选择排序


        一趟选择排序操作:

       通过n-i次关键字间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<=i<=n)个记录交换之。


       对L[1...n]中记录进行简单选择排序的算法为:令i从1至n-1,进行n-1趟选择操作。简单选择排序过程中,所需进行记录移动的操作次数较少,然而,无论记录的初始排列如何,所需关键字间的比较次数相同。因此,总的时间复杂度为O(n^2)。


示例代码(C语言描述):

/********************************************************************* Author:李冰 date:2014-9-11 Email:libing1209@126.com @array: the pointer to the records @length:the length of the records*********************************************************************///交换数据void Swap(int *num1, int *num2){int tmp = *num1;*num1 = *num2;*num2 = tmp;}void SelectSort(int array[], int length){if(array == NULL || length <= 0)return;int i, j, index;for(i = 0; i < length; i++){index = i;for(j = i + 1; j < length; j++)if(array[j] < array[index])index = j;if(i != index)Swap(&array[i], &array[index]);}}

二、树形选择排序(锦标赛排序)

       树形选择排序又称锦标赛排序。首先对n个记录的关键字进行两两比较,然后在其中n/2个较小者之间再进行两两比较,如此重复,直至选出最小关键字的记录为止。该过程可用一颗有n个叶子结点的完全二叉树表示。

代码示例(C语言描述):

/* * 对树进行筛选:从叶子节点开始,两两一起选出最小的,作为双亲 */static void AdjustTree(int *Tree,int length,int high){/*调整至根节点,结束调整*/if(length==1){return;}else{int nextlength=(length+1)/2;int adjustpos=high-length+1-nextlength;/*选择两个叶子,选择其中较小的作为两个叶子的双亲*/for(int i=high-length+1;i<=high;i+=2){/* * 可能最后一个选择时,只有一个叶子,即奇数个叶子 * 依然应该把剩下的叶子Tree[i]作为自己的双亲 * 所以 i<high 不能丢 */if( (i<high)&&(Tree[i]>Tree[i+1]) ){Tree[adjustpos]=Tree[i+1];}else{Tree[adjustpos]=Tree[i];}adjustpos++;}AdjustTree(Tree,nextlength,high-length);}}/* * 根据最底层节点个数n,返回整棵树的节点数 */static int GetTreeSize(int n){if(n==1){return 1;}else{return (n+GetTreeSize((n+1)/2));}}/* * 对sq+1,sq+2,sq+3,...,sq+length 进行树形选择排序 */void TreeSelectSort(int *sq,int length){/*根据叶子节点数为length,创建一个二叉树,用顺序存储结构表示*//* 7个叶子,需要节点数为 7+4+2+1=14                O              /    \             O       O            /\      / \           O  O    O   O          /\  /\  /\  /          O  OO O O  OO*//*Tree指向这个二叉树的指针,TreeSize保存二叉树的节点总数*/int TreeSize=0;int *Tree=NULL;TreeSize=GetTreeSize(length);//printf("\nTreeSize=%d\n",TreeSize);Tree=(int *)malloc(TreeSize*sizeof(int));if(Tree!=NULL){memset(Tree,0,TreeSize*sizeof(int));//复制序列到树结构中for(int i=TreeSize-length,j=1;i<TreeSize;i++,j++){Tree[i]=sq[j];}for(int pos=1;pos<=length;){AdjustTree(Tree,length,TreeSize-1);printf("Min node =%d\n",Tree[0]);//选出所有关键字等于当前最小的记录,填到结果中for(int i=TreeSize-length;i<TreeSize;i++){if(Tree[i]==Tree[0]){Tree[i]=MAX_INT;/* * 20120910更改此处的 break * 原因是:如果有大量数据重复,对每个重复的数据也进行选择效率太低 * 对一个关键字选择后,对所有关键字等于这个关键字的记录都应不再进行选择 *///break;sq[pos]=Tree[0];pos++;/* * 注意这点:pos++ 的位置,并没有放在for循环中 * 因为每次筛选出来的最小关键字肯定存在于叶子节点中 * if(Tree[i]==Tree[0])至少成立一次 * 如果不止成立一次,即有相同关键字,则应该减少筛选次数 */}}}free(Tree);Tree=NULL;}}

       由于含有 n 个叶子节点的完全二叉树的深度为  『( log2(N) )+1 ,则在树形选择排序中除最小关键字之外,每选择一个次小关键字仅需进行 『( log2(N) )次比较,因此它的时间复杂度为 O(NlogN)。『代表上取整


参考文献:

1、《数据结构(C语言描述)》 严蔚敏 吴伟东 编著

2、http://blog.csdn.net/to_be_it_1/article/details/37866391

3、http://blog.csdn.net/zhccl/article/details/7960983

4、http://blog.csdn.net/morewindows/article/details/6671824


0 0
原创粉丝点击