简单介绍几种排序算法
来源:互联网 发布:手绘自拍软件 编辑:程序博客网 时间:2024/05/19 18:38
选择排序
简单选择排序
比如从小到大排序的话,从未排序序列中选出最小的和序列的首元素交换,然后再在剩下的未排序序列中选出最小的和序列的第二个元素交换,以此类推,最后形成从小到大的已排序序列。C语言代码解释如下:
void SimpleSelectionSort(ElementType A[],int N){ int i,j,min,temp; for(i=0;i<N-1,i++){ min=i; for(j=i+1,j<N;j++){ if(A[min]>A[j]){ //确定较小元素的位置 min=j; } } //交换元素的值 temp=A[i]; A[i]=A[min]; A[min]=temp; }}
堆排序
字面意思就是用堆这种数据结构所设计的排序算法。堆是一种特殊的二叉树,每个子节点的值总是大于或小于他的父节点,相应的分为最小堆和最大堆。C语言解释代码:
void Ajust(ElementType A[],int i,int N){ int child; Element temp; //将当前元素的节点和其子节点比较,将最大值放到父节点上 for(temp=A[i];(2*i+1)<N;i=child){ child=2*i+1; if((child!=N-1)&&(A[child+1]>A[child])){ child++; } if(temp<A[child]){ A[i]=A[child]; } else break; } A[i]=temp;//将temp放到当前位置}void heapSort(ElementType A[],int N){ int i; ElementType temp; //建立最大推 for(i=(N-1)/2;i>=0;i++){ Ajust(A,i,N); } for(i=N-1;i>0;i--){ //将堆顶元素与当前堆的最后一个元素i互换 temp=A[0];A[0]=A[i];A[i]=temp; //重新建立最大堆 Ajust(A,0,i); }}
插入排序
简单插入排序
核心思想是将待排序的序列分为已排序序列和未排序序列。比如一个未排序序列,直接默认已排序序列只有第一个元素这种就行。C语言解释代码:
void InsertionSort(ElementType A[],int N){int i,j;ElementType temp; for(i=0;i<N;i++){ temp=A[i]; for(j=i;(j<0)&&(temp<A[j-1]);j--){ A[j]=A[j-1];//将已排序元素大于当前temp的元素右移 } A[j]=temp;//将当前的temp元素放入合适位置 }}
希尔排序
希尔排序是每次交换间隔一定距离的元素(比如1,3,6,4,5;取其中的1和4,就相当于间隔3;类似的直到间隔为1则完成了最终排序),C语言解释代码:
void ShellSort(ElementType A[],int N,int Incre[],int M){ //Incre[]为排序增量的数组,最后一个元素的值为1(说明排序完成) int i,j;k,Increment; ElementType temp; for(i=0;i<M;i++){ Increment=Incre[i];//选择排序的增量 //进行一次增量排序 for(j=Increment;j<N;j++){ temp=A[j]; for(k=j;k-Increment>=0;k-=Increment){ if(temp>=A[k-Increment])break; else A[k]=A[k-Increment]; A[k]=temp; } } }}
交换排序
冒泡排序
最简单的交换排序,通过不断循环将最大或者最小元素交换出来,放到未排序元素的最后。C语言解释代码:
void BubbleSort(ElementType A[],int N){ int i,j; bool flag; ElementType temp; for(i=N-1;i>=0;i--){ //初始时标记未交换 flag=0; //循环找出最大元素放到最右端 for(j=0;i<i;j++){ if(A[j]>A[j+1]){ temp=A[j]; A[j]=A[j+1]; A[j+1]=temp; //标记是否交换 flag=1; } } if(!flag)break;//如果一次未发生交换说明有序,跳出循环 }}
快速排序
原理是将未排序的元素根据基准分为两个子序列,一个子序列均大于基准,另一个均小于基准,然后递归的对这两个子序列用类似方法排序。C语言解释代码:
//交换两个元素的值void Swap(ElementType *a,ElementType *b){ ElementType temp=*a; *a=*b; *b=temp;}void Qsort(ElementType A[],int Low,int High){ //以第一个元素为基准 ElementType Pivot=A[low]; //保存初始的最大最小元素位置 int Left=Low,Right=High; if(Low>=High) return; //基准先放到最后 Swap(&A[Low],&A[High]); //将比基准小的移到基准左边,比基准大的移到基准右边 while(1){ while((Low<High)&&(Pivot>=A[Low])) Low++; while((Low<High)&&(Pivot<=A[High])) High--; if(Low<High) Swap[&A[Low],&A[High]]; else break; } //基准回到中间 Swap(&A[Low],&A[High]); //分别对左右两个边的序列继续快排 Qsort(A,Left,Low-1); Qsort(A,low+1,Right);}//执行快排void QuikSort(ElementType A[],int N){ Qsort(A,0,N-1);}
归并排序
归并排序是指将两个已排序的子序列合成一个有序序列的过程。原理是:可以将大小为N的序列看成N个长度为1的子序列,然后两两归并,形成一个N/2长度的长度为2的子序列有序序列,然后继续将相邻的子序列两两归并,如此循环直到最后剩下一个长度为N的序列。
//将两个序列归并void merge(ElementType A[],ElementType TmpA[],int Left,int Mid,int Right){ int Tp,LeftEnd,i; Tp=Left; LeftEnd=Mid-1; while((Left>LeftEnd)&&(Mid<Right)){ //如果左序列元素比右序列大,则将左边元素移入临时序列 if(A[Left]<=A[Mid]) TmpA[Tp++]=A[Left++]; else //如果右序列元素比左序列大,则将右边元素移入临时序列 TmpA[Tp++]=A[Mid++]; } while(Left<=LeftEnd)//满足说明右边序列元素已经没了 //将剩余的左边元素复制到临时序列 TmpA[Tp++]=A[Left++]; while(Mid<=Right)//满足说明左边序列元素已经都没了 //将剩余的右边元素复制到临时序列 TmpA[Tp++]=A[Mid++]; //将临时序列放回到A中 for(i=Right-Left;i>=0;i--,Right--){ A[Right]=TmpA[Right]; }}//递归排序void Msort(ElementType A[],ElementType TmpA[],int Left,int Right){ if(Left<Right){ Msort(A,TmpA,Left,(Left+Right)/2); Msort(A,TmpA,(Left+Right)/2+1,Right); merge(A,TmpA,Left,(Left+Right)/2,Right); }}//排序方法(执行方法)void MergeSort(){ ElementType *TmpA; TmpA=malloc(N*sizeof(ElementType)); Msort(A,TmpA,0,N-1); free(TmpA);}
基数排序
基数排序可以看成桶排序。桶排序是将关键字的每个可能的取值建立一个桶,扫描所有序列元素,按照关键字放入对应的桶中,然后再按照桶的顺序收集一遍自然就有序。而基数排序属于桶排序的一种推广,所考虑的待排序记录的关键字不止一个。
对于一般有K个关键字的基数排序,通常有两种方法:主位优先法(MSD)和次位优先法(LSD)。
下面是次位优先法的C语言代码解释实现(有待研究):
typedef struct Node *PtrToNode;typedef PtrToNode List;struct Node{ int Key[MaxDigit]; PtrToNode Next;};List RadixSort(List A){ List Bucket[Radix];//建立Radix个桶 List Bear[Radix];//需要记录每个桶的链表的尾元素的位置 int i,j,Digit; for(i=MaxDigit-1;i>=0;i--){//从最次关键字开始 for(j=0;j<Radix;j++) Bucket[j]=Rear[j]=NULL; while(A){//将关键字逐一分配到桶 Digit=A->Key[i]; if(!Bucket[Digit]){ Bucket[Digit]=A; }else{ Rear[Digit]->Next=A; } Rear[Digit]=A; A=A->Next; } for(j=Radix-1;j>=0;j--){ if(Bucket[j]){ Rear[j]->Next=A; A=Bucket[j]; } } } return A;}
各算法效率比较
注:
1、稳定是指是否在排序后改变原有等值元素的顺序。
2、基数排序中的D为分配收集的趟数,也就是关键字按基数分解后的位数
以上
参考文献:高等教育出版社出版的陈越主编的《数据结构》
- 简单介绍几种排序算法
- 几种简单排序算法
- 几种简单排序算法
- 数据结构:几种排序算法的介绍。
- 几种排序算法java简单实现
- 几种简单的排序算法
- 几种简单的排序算法
- 几种简单的排序算法
- 简单的几种排序算法源码
- 几种简单的排序算法
- 几种简单的排序算法
- 几种排序算法的简单总结
- 几种常见简单排序算法
- JAVA 中的几种简单排序算法
- 几种简单的排序算法
- 几种简单的排序算法
- 几种简单的排序算法
- 几种简单排序算法详解
- WFMLRSVCApp.ear not found
- java synchronized 用法
- 使用Gradle编译出错Failed converting ECJ parse tree to Lombok
- 开发商问题的初始需求建立
- js实现左右轮播图效果
- 简单介绍几种排序算法
- C++ 包含目录、库目录、附加依赖项总结
- 项目从计划到上线的大概流程
- ACM篇:POJ 1083 -- Moving Tables
- 决策树及MATLAB函数使用
- php复习 第十四天 与数据库交互
- AfxBeginThread创建线程时出现内存不足
- 快捷实现网络请求Retrofit
- Git 少用 Pull 多用 Fetch 和 Merge