排序(Sort)是计算机程序设计中的一种重要操作,也是日常生活中经常遇到的问题。例如,字典中的单词是以字母的顺序排列,否则,使用起来非常困难。同样,存储在计算机中的数据的次序,对于处理这些数据的算法的速度和简便性而言,也具有非常深远的意义。

排序分为:外部排序 and 内部排序

这里我们讨论内部排序

 

冒泡排序法

冒泡排序法的基本思想是:对待排序记录关键字从后往前(逆序)进行多遍扫描,当发现相邻两个关键字的次序与排序要求的规则不符时,就将这两个记录进行交换。这样,关键字较小的记录将逐渐从后面向前面移动,就象气泡在水中向上浮一样,所以该算法也称为气泡排序法。

                                 

 

编写一个随机生成数列的函数<CreateData>:

#include <stdlib.h>
int CreateData(int arr[],int n,int min,int max) //创建一个随机数组,a保存生成的数据,n为数组元素的数量
{
int i,j,flag;
srand(time(NULL));
if((max-min+1)<n) return 0; //最大数与最小数之差小于产生数组的数量,生成数据不成功
for(i=0;i<n;i++)
{
do
{
arr[i]=(max-min+1)*rand()/(RAND_MAX+1)+min;
flag=0;
for(j=0;j<i;j++)
{
if(arr[i]==arr[j])
flag=1;
}
}while(flag);
}
return 1;
}

 

编写冒泡排序法程序:

void BubbleSort(int a[],int n)
{
int i,j,t;
for(i=0;i<n-1;i++)
{
for(j=n-1;j>i;j--)
{
if(a[j-1]>a[j])
{
t=a[j-1];
a[j-1]=a[j];
a[j]=t;
}
}
printf("第%2d遍:",i+1);
for(j=0;j<n;j++)
printf("%d ",a[j]);
printf("\n");
}
}

测试:

int main()
{
int i,a[ARRAYLEN];
for(i=0;i<ARRAYLEN;i++)
a[i]=0;
if(!CreateData(a,ARRAYLEN,1,100))
{
printf("生成随机数不成功!\n");
getch();
return 1;
}
printf("原数据:");
for(i=0;i<ARRAYLEN;i++)
printf("%d ",a[i]);
printf("\n");
BubbleSort(a,ARRAYLEN);
printf("排序后:");
for(i=0;i<ARRAYLEN;i++)
printf("%d ",a[i]);
printf("\n");
getch();
return 0;
}

结果:

我们发现,在第三遍时我们就已经排序完毕,可是还是进行了第四第五遍,所以为了提升冒泡排序法的效率,可对BubbleSort函数进行改进,当在某一遍扫描时,发现数据都已经按顺序排列了,就不再进行后继的扫描,而结束排序过程。

该进就是对其添加了一个标志位,当已经排序好之后,就加上标志位不再排序。

void BubbleSort1(int a[],int n)
{
int i,j,t,flag=0; //flag用来标记是否发生交换
for(i=0;i<n-1;i++)
{
for(j=n-1;j>i;j--)
{
if(a[j-1]>a[j])//交换数据
{
t=a[j-1];
a[j-1]=a[j];
a[j]=t;
flag=1;
}
}
printf("第%2d遍:",i+1);
for(j=0;j<n;j++)
printf("%d ",a[j]);
printf("\n");
if(flag==0) //没发生交换,直接跳出循环
break;
else
flag=0;
}
}

 


快速排序法

快速排序使用分治策略来把待排序数据序列分为两个子序列,具体步骤为:

(1)从数列中挑出一个元素,称该元素为“基准”。

(2)扫描一遍数列,将所有比“基准”小的元素排在基准前面,所有比“基准”大的元素排在基准后面。

(3)通过递归,将各子序列划分为更小的序列,直到把小于基准值元素的子数列和大于基准值元素的子数列排序。

快速排序详细步骤:

以一个数组作为示例,取区间第一个数为基准数。

初始时,i = 0;  j = 9;   X = a[i] = 72

由于已经将a[0]中的数保存到X中,可以理解成在数组a[0]上挖了个坑,可以将其它数据填充到这来。

从j开始向前找一个比X小或等于X的数。当j=8,符合条件,将a[8]挖出再填到上一个坑a[0]中。a[0]=a[8]; i++;  这样一个坑a[0]就被搞定了,但又形成了一个新坑a[8],这怎么办了?简单,再找数字来填a[8]这个坑。这次从i开始向后找一个大于X的数,当i=3,符合条件,将a[3]挖出再填到上一个坑中a[8]=a[3]; j--;

数组变为:

i = 3;   j = 7;   X=72

再重复上面的步骤,先从后向前找,再从前向后找。

从j开始向前找,当j=5,符合条件,将a[5]挖出填到上一个坑中,a[3] = a[5]; i++

从i开始向后找,当i=5时,由于i==j退出。

此时,i = j = 5,而a[5]刚好又是上次挖的坑,因此将X填入a[5]。

数组变为:

可以看出a[5]前面的数字都小于它,a[5]后面的数字都大于它。因此再对a[0…4]和a[6…9]这二个子区间重复上述步骤就可以了。

/// <summary>
/// 对数组dataArray中索引从left到right之间的数做排序
/// </summary>
/// <param name="dataArray"></param>
/// <param name="left">要排序数组的开始索引</param>
/// <param name="right">要排序数组的结束索引</param>
private static void QuickSort(int[] dataArray,int left,int right)
{
if (left < right)
{
int x = dataArray[left];//基准数 小的放左边 大的放右边
int i = left;
int j = right;//用来做循环的标志位 while (true && i < j)
{
//从右向左比较
while (true && i < j)
{
if (dataArray[j] <= x) //找到了一个比基准数 小于等于的数字 应该把它放在x的左边
{
dataArray[i] = dataArray[j];
break;
}
else
{
j--; //向左移动 到下一个数字 然后做比较
}
} //从左向右比较
while (true && i < j)
{
if (dataArray[i] > x)
{
dataArray[j] = dataArray[i];
break;
}
else
{
i++;
}
}
} //跳出循环 现在i=j i是中间位置
dataArray[i] = x;//left-i-right QuickSort(dataArray, left, i - 1);
QuickSort(dataArray, i + 1, right);
}
}

测试:

static void Main(string[] args)
{
int[] data = new int[] { 42, 20, 17, 27, 13, 8, 17, 48 }; QuickSort(data,0,data.Length-1); foreach (var temp in data)
{
Console.Write(temp + " ");
} Console.ReadKey();
}

结果:

因为可能数据量比较小 所以看不出前二种方法的区别 可以试着增加数据量比较一下

常用算法——排序(一)的更多相关文章

  1. 常用算法——排序(二)

    简单选择排序法 选择排序(Selection Sort)的基本思想:对n个记录进行扫描,选择最小的记录,将其输出,接着在剩下的n-1个记录中扫描,选择最小的记录将其输出,--不断重复这个过程,直到只剩 ...

  2. 常用算法——排序(三)

    希尔排序法 希尔排序又称为缩小增量排序,也属于插入排序类的算法,是对直接插入排序的一种改进. 基本思想就是:将需要排序的序列划分为若干个较小的序列,对这些序列进行直接插入排序,通过这样的操作可使用需要 ...

  3. JavaScript实现常用的排序算法

    ▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排 ...

  4. 常用Java排序算法

    常用Java排序算法 冒泡排序 .选择排序.快速排序 package com.javaee.corejava; public class DataSort { public DataSort() { ...

  5. js算法之最常用的排序

    引入 大学学习计算机语言的那几年,从c语言,到c++,再到数据结构JAVA..让我印象最深刻的还是最开始老师讲冒泡算法的时候,直到现在大四快毕业了我才渐渐通窍了.刚学前端的时候以为前端就是做出好看很炫 ...

  6. java SE 常用的排序算法

    java程序员会用到的经典排序算法实现 常用的排序算法(以下代码包含的)有以下五类: A.插入排序(直接插入排序.希尔排序) B.交换排序(冒泡排序.快速排序) C.选择排序(直接选择排序.堆排序) ...

  7. C#中常用的排序算法的时间复杂度和空间复杂度

    常用的排序算法的时间复杂度和空间复杂度   常用的排序算法的时间复杂度和空间复杂度 排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度 冒泡排序 O(n2) O(n2) 稳定 O(1) 快速排序 ...

  8. 数据结构中常用的排序算法 && 时间复杂度 && 空间复杂度

    第一部分:数据结构中常用的排序算法 数据结构中的排序算法一般包括冒泡排序.选择排序.插入排序.归并排序和 快速排序, 当然还有很多其他的排序方式,这里主要介绍这五种排序方式. 排序是数据结构中的主要内 ...

  9. 常用算法之排序(Java)

    一.常用算法(Java实现) 1.选择排序(初级算法) 原理:有N个数据则外循环就遍历N次并进行N次交换.内循环实现将外循环当前的索引i元素与索引大于i的所有元素进行比较找到最小元素索引,然后外循环进 ...

随机推荐

  1. .NET Core采用的全新配置系统[7]: 将配置保存在数据库中

    我们在<聊聊默认支持的各种配置源>和<深入了解三种针对文件(JSON.XML与INI)的配置源>对配置模型中默认提供的各种ConfigurationSource进行了深入详尽的 ...

  2. How to debug .NET Core RC2 app with Visual Studio Code on Windows?

    Simone Chiaretta (http://codeclimber.net.nz/archive/2016/05/20/How-to-debug-NET-Core-RC2-app-with-Vi ...

  3. 开源Word读写组件DocX 的深入研究和问题总结

    一. 前言 前两天看到了asxinyu大神的[原创]开源Word读写组件DocX介绍与入门,正好我也有类似的自动生成word文档得需求,于是便仔细的研究了这个DocX. 我也把它融入到我的项目当中并进 ...

  4. [.Net] 手把手带你将自己打造的类库丢到 NuGet 上

    手把手带你将自己打造的类库丢到 NuGet 上 序 我们习惯了对项目右键点击“引用”,选择“管理NuGet 程序包”来下载第三方的类库,可曾想过有一天将自己的打造的类库放到 NuGet 上,让第三者下 ...

  5. C#/ASP.NET完善的DBHelper,配套Model生成器

    支持Oracle.MSSQL.MySQL.SQLite四种数据库,支持事务,支持对象关系映射:已在多个项目中实际使用. 没有语法糖,学习成本几乎为0,拿来即用. DBHelper类完整代码: usin ...

  6. 绑定一个值给radio

    在ASP.NET MVC程序中,需要给一个radio list表绑定一个值. 下面是Insus.NET实现的方法: 使用foreach来循环radio每一个选项,如果值与选项的值相同,那这个选项为选中 ...

  7. php N 维数组的读取、设置、删除

    <?php // 例子 $rowList = array(); $rowList[] = array('A'=>'A_1','B'=>'A_1_1','C'=>'A_1_1_1 ...

  8. 【Java每日一题】20161226

    package Dec2016; public class Ques1226 { static{ num = 1; } public static int num = 2; public static ...

  9. 使用do{ } while(0)的好处

    经常看到好多程序,尤其是linux相关的,使用do{}while(0)的写法,很明显内部程序最多只能执行一次,这样写的原因是什么呢?个人认为主要的原因是,如果不使用do{}while(0),那么当一个 ...

  10. 弹出iframe内嵌页面元素到父页面并全屏化

    (注册博客好久了,一直没舍得添砖加瓦,主要是每次想写点东西的时候,随便搜一搜发现都比我总结的都要好,甚感尴尬,但是总是要开始的,所以这就是我的第一篇博客,也绝不会是最后一篇,废话不多说,直接入正题) ...