C#排序算法的比较分析

本文实例分析了C#的各种排序算法。分享给大家供大家参考。具体分析如下:

首先通过图表比较不同排序算法的时间复杂度和稳定性。



排序方法



平均时间



最坏情况



最好情况



辅助空间



稳定性

直接插入排序
O(n

2

)


O(n

2

)


O(n)


O(1)

冒泡排序
O(n

2

)


O(n

2

)


O(n)


O(1)

简单选择排序
O(n

2

)


O(n

2

)


O(n

2

)


O(1)

希尔排序
O(nlog

2

n)~O(n

2

)


O(nlog

2

n)~O(n

2

)


O(1)

快速排序
O(nlog

2

n)


O(n

2

)


O(nlog

2

n)


O(log

2

n)

堆排序
O(nlog

2

n)


O(nlog

2

n)


O(nlog

2

n)


O(1)

2-路归并排序
O(nlog

2

n)


O(nlog

2

n)


O(nlog

2

n)


O(n)

基数排序 O(d(n + rd)) O(d(n + rd)) O(d(n + rd)) O(rd)


注:

1. 算法的时间复杂度一般情况下指最坏情况下的渐近时间复杂度。

2. 排序算法的稳定性会对多关键字排序产生影响。

下面通过C#代码说明不同的排序算法


插入排序

时间复杂度:平均情况―O(n2) 最坏情况―O(n2) 辅助空间:O(1) 稳定性:稳定

插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。

代码如下:

void InsertSort(SqList &L;) {

// 对顺序表L作直接插入排序。

int i,j;

for (i=2; i<=L.length; ++i)

if (LT(L.r[i].key, L.r[i-1].key)) {

// “<“时,需将L.r[i]插入有序子表

L.r[0] = L.r[i];                 // 复制为哨兵

for (j=i-1;  LT(L.r[0].key, L.r[j].key);  –j)

L.r[j+1] = L.r[j];             // 记录后移

L.r[j+1] = L.r[0];               // 插入到正确位置

}

} // InsertSort


希尔排序(shell)

时间复杂度:理想情况―O(nlog2n) 最坏情况―O(n2) 稳定性:不稳定

希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

代码如下:

void ShellInsert(SqList &L;, int dk) {

// 对顺序表L作一趟希尔插入排序。本算法对算法10.1作了以下修改:

//     1. 前后记录位置的增量是dk,而不是1;

//     2. r[0]只是暂存单元,不是哨兵。当j<=0时,插入位置已找到。

int i,j;

for (i=dk+1; i<=L.length; ++i)

if (LT(L.r[i].key, L.r[i-dk].key)) { // 需将L.r[i]插入有序增量子表

L.r[0] = L.r[i];                   // 暂存在L.r[0]

for (j=i-dk; j>0 && LT(L.r[0].key, L.r[j].key); j-=dk)

L.r[j+dk] = L.r[j];              // 记录后移,查找插入位置

L.r[j+dk] = L.r[0];                // 插入

}

} // ShellInsert

void ShellSort(SqList &L;, int dlta[], int t) {

// 按增量序列dlta[0..t-1]对顺序表L作希尔排序。

for (int k=0;k<t;k++)

ShellInsert(L, dlta[k]);  // 一趟增量为dlta[k]的插入排序

} // ShellSort


冒泡排序

时间复杂度:平均情况―O(n2) 最坏情况―O(n2) 辅助空间:O(1) 稳定性:稳定

冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。

代码如下:

void BubbleSort(SeqList R) {

int i,j;

Boolean exchange; //交换标志

for(i=1;i<n;i++){ exchange=”FALSE;” j=”n-1;j”>=i;j–) //对当前无序区R[i..n]自下向上扫描

if(R[j+1].key< R[j].key){//交换记录

R[0]=R[j+1]; //R[0]不是哨兵,仅做暂存单元

R[j+1]=R[j];

R[j]=R[0];

exchange=TRUE; //发生了交换,故将交换标志置为真

}

if(!exchange) //本趟排序未发生交换,提前终止算法

return;

} //endfor(外循环)

}


快速排序

时间复杂度:平均情况―O(nlog2n) 最坏情况―O(n2) 辅助空间:O(log2n) 稳定性:不稳定

快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走,当a[j] > a[center_index]。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。 交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11, 现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j]交换的时刻。

代码如下:

int Partition(SqList &L;, int low, int high) {

// 交换顺序表L中子序列L.r[low..high]的记录,使枢轴记录到位,

// 并返回其所在位置,此时,在它之前(后)的记录均不大(小)于它

KeyType pivotkey;

RedType temp;

pivotkey = L.r[low].key;     // 用子表的第一个记录作枢轴记录

while (low < high) {           // 从表的两端交替地向中间扫描

while (low < high && L.r[high].key>=pivotkey) –high;

temp=L.r[low];

L.r[low]=L.r[high];

L.r[high]=temp;           // 将比枢轴记录小的记录交换到低端

while (low  < high && L.r[low].key < =pivotkey) ++low;

temp=L.r[low];

L.r[low]=L.r[high];

L.r[high]=temp;           // 将比枢轴记录大的记录交换到高端

}

return low;                  // 返回枢轴所在位置

} // Partition

void QSort(SqList &L;, int low, int high) {

// 对顺序表L中的子序列L.r[low..high]进行快速排序

int pivotloc;

if (low  <  high) {                      // 长度大于1

pivotloc = Partition(L, low, high);  // 将L.r[low..high]一分为二

QSort(L, low, pivotloc-1); // 对低子表递归排序,pivotloc是枢轴位置

QSort(L, pivotloc+1, high);          // 对高子表递归排序

}

} // QSort

void QuickSort(SqList &L;) {

// 对顺序表L进行快速排序

QSort(L, 1, L.length);

} // QuickSort

除声明外,跑步客文章均为原创,转载请以链接形式标明本文地址
  C#排序算法的比较分析

本文地址:  http://www.paobuke.com/develop/c-develop/pbk23333.html

相关内容

C#基于TCP协议的服务器端和客户端通信编程的基础教程

C#使用LINQ中Enumerable类方法的延迟与立即执行的控制

C#.NET中如何批量插入大量数据到数据库中

C#读取配置文件的方法汇总


C#实现简单聊天程序的方法

C#实现的文件压缩和解压缩类

C#定时器实现自动执行的方法

C#获取真实IP地址实现方法

时间: 2024-10-11 19:53:28

C#排序算法的比较分析的相关文章

常用排序算法比较与分析

一.常用排序算法简述 下面主要从排序算法的基本概念.原理出发,分别从算法的时间复杂度.空间复杂度.算法的稳定性和速度等方面进行分析比较.依据待排序的问题大小(记录数量 n)的不同,排序过程中需要的存储器空间也不同,由此将排序算法分为两大类:[内排序].[外排序]. 内排序:指排序时数据元素全部存放在计算机的随机存储器RAM中. 外排序:待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中还需要对外存进行访问的排序过程. 先了解一下常见排序算法的分类关系(见图1-1) 图1-1 常见排

排序算法比较与分析

一.常用排序算法简述 下面主要从排序算法的基本概念.原理出发,分别从算法的时间复杂度.空间复杂度.算法的稳定性和速度等方面进行分析比较.依据待排序的问题大小(记录数量  n)的不同,排序过程中需要的存储器空间也不同,由此将排序算法分为两大类:[内排序].[外排序]. 内排序:指排序时数据元素全部存放在计算机的随机存储器RAM中. 外排序:待排序记录的数量很大,以致内存一次不能容纳全部记录,在排序过程中还需要对外存进行访问的排序过程. 先了解一下常见排序算法的分类关系(见图1-1) 图1-1 常见

各种排序算法的稳定性分析

(1)冒泡排序 冒泡排序就是把小的元素往前调或者把大的元素往后调.比较是相邻的两个元素比较,交换也发生在这两个元素之间.所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的:如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法. (2)选择排序 选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个

排序-算法复杂度分析

......

内部排序算法(一):交换排序(冒泡排序,快速排序)

这是我的博文系列<内部排序算法>的第一篇.所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来.所谓内部排序,是指在排序过程中,若整个文件都是放在内存中处理,排序时不涉及数据的内.外存交换(外排序的定义则相反). 内部排序法按照策略可以划分为五类:插入排序.选择排序.交换排序.归并排序和分配排序.待排文件的存储方式采用顺序表(或直接用向量)作为存储结构(其他的存储结构还有以链表作为存储结构等). 在这个系列的博文中,我按照排序算法的给出,排序算法的分析(包括算法的时空复杂度

数据结构—各类‘排序算法’实现(下)

在上一篇博客中,主要是实现各种的排序算法,并针对一些算法进行了优化的处理,下面主要讨论一下非比较排序的算法(计数排序.基数排序),同时并对各种排序算法的性能.时间复杂度.空间复杂度.优缺点.以及适用场景做总结分析. 1.计数排序 主要思想:主要是需要统计次数,使用直接定址法,统计最大数和最小数,开辟两个数相差的空间大小,对于重复数据,使用count用来计数,时间复杂度O(N+范围个数),空间复杂度O(范围个数)计数排序适合于数据较为密集的情况,当数据密集且没有重复的数据,可以直接使用'位图',更

十种常见排序算法

1.常见算法分类 十种常见排序算法一般分为以下几种: (1)非线性时间比较类排序:交换类排序(快速排序和冒泡排序).插入类排序(简单插入排序和希尔排序).选择类排序(简单选择排序和堆排序).归并排序(二路归并排序和多路归并排序): (2)线性时间非比较类排序:计数排序.基数排序和桶排序. 总结: (1)在比较类排序中,归并排序号称最快,其次是快速排序和堆排序,两者不相伯仲,但是有一点需要注意,数据初始排序状态对堆排序不会产生太大的影响,而快速排序却恰恰相反. (2)线性时间非比较类排序一般要优于

排序算法 之 效率测试

前面我们写了常见的几种排序算法,并分析了各种算法的实现思想,及时间复杂度等情况,但由于只是分析,木有实际的数据做对比测试,所以对各个算法的效率也没有一个明确的概念,下面我们就通过具体的测试来看看同算法之间的效率差距. 声明11个长度为100的元素取值范围为0到1000的序列 int length = 100; int[] testArray1 = new int[length]; int[] testArray2 = new int[length]; int[] testArray3 = new

PHP四种基本排序算法

PHP的四种基本排序算法为:冒泡排序.插入排序.选择排序和快速排序. 下面是我整理出来的算法代码: 1. 冒泡排序: 思路:对数组进行多轮冒泡,每一轮对数组中的元素两两比较,调整位置,冒出一个最大的数来. //简单版: function bubbleSort($arr) { $n = count($arr); for($i=1;$i<$n;$i++) {   //冒泡的轮数(最多$n-1轮) for($j=0;$j<$n-1;$j++) {   //每一轮冒泡(两两比较,大者后移) if($a