常用算法——排序(一)
排序(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();
}
结果:
因为可能数据量比较小 所以看不出前二种方法的区别 可以试着增加数据量比较一下
常用算法——排序(一)的更多相关文章
- 常用算法——排序(二)
简单选择排序法 选择排序(Selection Sort)的基本思想:对n个记录进行扫描,选择最小的记录,将其输出,接着在剩下的n-1个记录中扫描,选择最小的记录将其输出,--不断重复这个过程,直到只剩 ...
- 常用算法——排序(三)
希尔排序法 希尔排序又称为缩小增量排序,也属于插入排序类的算法,是对直接插入排序的一种改进. 基本思想就是:将需要排序的序列划分为若干个较小的序列,对这些序列进行直接插入排序,通过这样的操作可使用需要 ...
- JavaScript实现常用的排序算法
▓▓▓▓▓▓ 大致介绍 由于最近要考试复习,所以学习js的时间少了 -_-||,考试完还会继续的努力学习,这次用原生的JavaScript实现以前学习的常用的排序算法,有冒泡排序.快速排序.直接插入排 ...
- 常用Java排序算法
常用Java排序算法 冒泡排序 .选择排序.快速排序 package com.javaee.corejava; public class DataSort { public DataSort() { ...
- js算法之最常用的排序
引入 大学学习计算机语言的那几年,从c语言,到c++,再到数据结构JAVA..让我印象最深刻的还是最开始老师讲冒泡算法的时候,直到现在大四快毕业了我才渐渐通窍了.刚学前端的时候以为前端就是做出好看很炫 ...
- java SE 常用的排序算法
java程序员会用到的经典排序算法实现 常用的排序算法(以下代码包含的)有以下五类: A.插入排序(直接插入排序.希尔排序) B.交换排序(冒泡排序.快速排序) C.选择排序(直接选择排序.堆排序) ...
- C#中常用的排序算法的时间复杂度和空间复杂度
常用的排序算法的时间复杂度和空间复杂度 常用的排序算法的时间复杂度和空间复杂度 排序法 最差时间分析 平均时间复杂度 稳定度 空间复杂度 冒泡排序 O(n2) O(n2) 稳定 O(1) 快速排序 ...
- 数据结构中常用的排序算法 && 时间复杂度 && 空间复杂度
第一部分:数据结构中常用的排序算法 数据结构中的排序算法一般包括冒泡排序.选择排序.插入排序.归并排序和 快速排序, 当然还有很多其他的排序方式,这里主要介绍这五种排序方式. 排序是数据结构中的主要内 ...
- 常用算法之排序(Java)
一.常用算法(Java实现) 1.选择排序(初级算法) 原理:有N个数据则外循环就遍历N次并进行N次交换.内循环实现将外循环当前的索引i元素与索引大于i的所有元素进行比较找到最小元素索引,然后外循环进 ...
随机推荐
- springmvc+jpa实现分页的两种方式
1.工具类 public final class QueryTool { public static PageRequest buildPageRequest(int pageNumber, int ...
- 谁是2016年的.NET开发者?
Nora Georgieva (http://www.telerik.com/blogs/infographic-the-dotnet-developer-of-2016) Whether you h ...
- 你可能不知道的陷阱, IEnumerable接口
1. IEnumerable 与 IEnumerator IEnumerable枚举器接口的重要性,说一万句话都不过分.几乎所有集合都实现了这个接口,Linq的核心也依赖于这个万能的接口.C语言的 ...
- 【NLP】揭秘马尔可夫模型神秘面纱系列文章(四)
维特比算法解决隐马尔可夫模型解码问题(中文句法标注) 作者:白宁超 2016年7月12日14:08:28 摘要:最早接触马尔可夫模型的定义源于吴军先生<数学之美>一书,起初觉得深奥难懂且无 ...
- JavaScript易错知识点整理
前言 本文是我学习JavaScript过程中收集与整理的一些易错知识点,将分别从变量作用域,类型比较,this指向,函数参数,闭包问题及对象拷贝与赋值这6个方面进行由浅入深的介绍和讲解,其中也涉及了一 ...
- Jsp的九大对象,七大动作,三大指令
jsp九大内置对象:1>out 向客户端输出数据,字节流.如out.print(" dgaweyr"); 2>request 接收客户端的http请求.String g ...
- 【JS基础】算法
Math 对象 Math.sqrt() //返回一个数的平方根
- 如何用CSS画三角形
很多时候页面都需要一个或者多个小型三角形!多数人直接用PS扣个图片预览 下面用CSS简单画几个最终效果如下图 <div class="border-all-color"> ...
- Date小技巧:set相关操作及应用_获取当前月(季度/年)的最后一天
set操作还是有不少的,具体见 http://www.w3school.com.cn/jsref/jsref_obj_date.asp, 今天我就只说 setFullYear, setMonth, s ...
- 利用私有的API获得手机上所安装的所有应用信息(包括版本,名称,bundleID,类型)
MobileCoreService这个系统的库,里面有个私有的类LSApplicationWorkspace ,利用运行时可以获得私有类里面的方法,- (id)allInstalledApplicat ...