五种常用排序
来源:互联网 发布:数控编程软件怎么下载 编辑:程序博客网 时间:2024/05/17 09:05
最近在看数据结构,想把几个简单的排序在过一遍,发现还没那么容易,最简单的冒泡排序代码没那么容易敲出来。下面把5种排序复习一下:
1. 冒泡排序:
冒泡排序是最简单也是最常用的排序方法。其基本思想是(以升序为例):将序列看成一排竖着的气泡。最后一个元素与倒数第二个元素进行比较,小的往前拱,再将倒数第二个元素与倒数第三个元素比较,小的往前拱,...这样一次外循环后,第一个元素就是序列最小的元素。n次外循环后就将序列排列好了。具体的程序如下:
int temp; int num=0; int a[10]={13,2,5,18,7,12,9,10,15,6}; for(int i=0;i<10;i++) for(int j=9;j>=i;j--) { num++; if (a[j]<a[j-1]) { temp=a[j]; a[j]=a[j-1]; a[j-1]=temp; } } for (i=0;i<10;i++) { printf("%d ",a[i]); } printf("\n"); printf("%d\n",num);
改进后的冒泡排序算法:
冒泡排序是每次将最小的数往上推(通过由下往上的两两比较),但有的时候序列已经有一定顺序了,每次再去比较就会浪费时间。所以可以设立一个flag,当某一次比较没有数据发生交换时,证明已经排好了,后面的就不去用再继续了。具体程序如下:
int temp; int num=0; bool flag=false; int a[10]={13,2,5,18,7,12,9,10,15,6}; for(int i=0;i<10 && !flag;i++) { flag=true; for(int j=9;j>=i;j--) { flag=false; num++; if (a[j]<a[j-1]) { temp=a[j]; a[j]=a[j-1]; a[j-1]=temp; } } } for (i=0;i<10;i++) { printf("%d ",a[i]); } printf("\n"); printf("%d\n",num);
2.直接插入排序:
直接插入排序的思想是:把一个数插入到一个有序序列中,原先的序列已经是排好的了,所以要先要找到该元素的位置,将原先的序列移动,然后再将数字插入。代码如下:
if(Is_Full(pArr)) return false; if(pos<1 || pos>pArr->cnt+1) return false; for (int i=pArr->cnt-1;i>=pos-1;i--) pArr->pBase[i+1]=pArr->pBase[i]; pArr->pBase[pos-1]=val; pArr->cnt++;
直接插入也可以改进,改进后的插入排序时边比较边移动的,当找到合适的位置时就直接插入。代码如下:
if(Is_Full(pArr)) return false; int pos=pArr->cnt-1; for (int i=pos;i>=0;i--) { if (val<pArr->pBase[i]) { pArr->pBase[i+1]=pArr->pBase[i]; } else { pArr->pBase[i+1]=val; pArr->cnt++; return true; } } pArr->cnt++;
3.快速排序:
快速排序是效率比较高的排序算法,其又细分为几种,不过基本思想是一样的。只要思想是:选定序列的第一个数,先找到该数的真实位置,然后将序列以这个数分为两个部分,左边又选定第一个数,找到该数的真实位置,右边也选定第一个数,找到该数的真实位置,....不断找到子序列第一个数的真实位置,实际上是一个递归的过程。至于第一个数的真实位置时如何确定的,是同过两个标记来实现的,每次都与这个数比较进行移动或者赋值,具体见代码:
#include <stdio.h>void QuickSort(int* a,int low,int high); //数组名和指针可以互用int FindPos(int* a,int low,int high); //找到第一个元素的真实位置int main(){ int a[6]={1,3,0,2,5,4}; QuickSort(a,0,5); //low 为 0,high 为 5 for(int i=0;i<6;i++) printf("%d ",a[i]); printf("\n"); return 0;}//递归实现//快速排序的思想:先找到第一个元素的真实位置,在将其左右两部分分成两个序列,继续查找序列的第一个元素的真实位置void QuickSort(int* a,int low,int high){ int pos; if (low<high) { pos=FindPos(a,low,high); QuickSort(a,low,pos-1); QuickSort(a,pos+1,high); }}int FindPos(int*a,int low,int high){ int val=a[low]; //临时变量val存储第一个元素的值,用来比较 while (low<high) { while (low<high && a[high]>val) //右部分比val大就移动 high--; a[low]=a[high]; //否则就把值赋给a[low] while(low<high && a[low]<val) //左半部分比val小就移动 low++; a[high]=a[low]; //否则就赋给a[high] } a[low]=val; //最后low于high就指向了第一个元素的真实位置 return low;}
4.选择排序
选择排序与冒泡排序类似;其基本思想是:假设开始有0个有序数和n个无序数,经过一次排序后就变成了1个有序数和n-1个有序数了...,每一次排序都使有序数的个数+1,无序数的个数减一。主要代码如下:
int temp,b; int num=0; int a[10]={13,2,5,18,7,12,9,10,15,6}; for(int i=0;i<10;i++) { temp=i; for(int j=i+1;j<10;j++) if(a[temp]>a[j]) { temp=j; } if (i!=temp) { num++; //当n较小时,num的次数比冒泡排序小 b=a[temp]; a[temp]=a[i]; a[i]=b; } }
*当n的次数较小时,选择排序比冒泡排序快。
5.归并排序
归并排序相对来说比较复杂,也没有多研究,就看一下大概的思想和代码。主要的思想是:将序列等分排序,将序列分为两个子序列,再排好两个子序列后将其合并起来。子序列的排序有和主序列类似,也是将其分为两个子序列,...最后将所有序列归并起来即可(也是利用了递归的方法)。主要代码:
#include<stdio.h>// 一个递归函数void mergesort(int *num,int start,int end);// 这个函数用来将两个排好序的数组进行合并void merge(int *num,int start,int middle,int end);int main(){// 测试数组 int num[10]= {12,54,23,67,86,45,97,32,14,65};int i;// 排序之前printf("Before sorting:\n");for (i=0; i<10; i++) {printf("%3d",num[i]);}printf("\n");// 进行合并排序mergesort(num,0,9);printf("After sorting:\n");// 排序之后for (i=0; i<10; i++) {printf("%3d",num[i]);}printf("\n");return 0;}//这个函数用来将问题细分void mergesort(int *num,int start,int end){int middle;if(start<end) {middle=(start+end)/2;// 归并的基本思想// 排左边mergesort(num,start,middle);// 排右边mergesort(num,middle+1,end);// 合并merge(num,start,middle,end);}}//这个函数用于将两个已排好序的子序列合并void merge(int *num,int start,int middle,int end){int n1=middle-start+1; int n2=end-middle;// 动态分配内存,声明两个数组容纳左右两边的数组int *L=new int[n1+1];int *R=new int[n2+1];int i,j=0,k;//将新建的两个数组赋值for (i=0; i<n1; i++) {*(L+i)=*(num+start+i);}// 哨兵元素 *(L+n1)=1000000;for (i=0; i<n2; i++) {*(R+i)=*(num+middle+i+1);}*(R+n2)=1000000;i=0;// 进行合并for (k=start; k<=end; k++) {if(L[i]<=R[j]) {num[k]=L[i];i++;}else {num[k]=R[j];j++;}}delete [] L;delete [] R;}
- 五种常用排序
- java 常用五种排序
- 五种常用排序方法
- 常用排序算法总结(五)
- 常用的五大排序
- 五种比较高效常用的排序算法
- 用Java语言实现五种常用排序
- 五种排序算法
- 五种基本排序
- 常用算法总结之排序(五)----简单选择排序
- 常用内部排序算法之五:希尔排序
- 五种常用手势
- 五种常用算法
- Oracle排序中NULL值处理的五种常用方法
- Oracle排序中NULL值处理的五种常用方法
- Oracle排序中NULL值处理的五种常用方法
- Oracle排序中NULL值处理的五种常用方法
- Oracle排序中NULL值处理的五种常用方法
- Cassandra 使用Thrift API操作数据, 读写多行(range区间)多列(slice切片)数据
- ANDROID DisplayManager 服务解析一
- paip.获取当前实际北京时间API
- C#的virtual概念
- MySQL-访问权限与信息安全
- 五种常用排序
- C# 小程序之新手练习(五)15位身份证号转18位身份证号
- python及python web资料链接(持续更新中...)
- HP大中华区总裁孙振耀退休感言
- 应届生应该选择互联网大公司还是小团队
- lca转rmq
- sql实例不能启动的原因及处理
- 约瑟夫问题求解
- 黑马程序员----JAVA----IO小结(1)