软考笔记第六天之各排序算法的实现

对于前面的排序算法,用c#来实现

直接插入排序:

每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。
第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从前向后扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
直接插入排序属于稳定的排序,最坏时间复杂性为O(n^2),空间复杂度为O(1)。
直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的数值。内层循环为待比较数值确定其最终位置。直接插入排序是将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的。当前一数值比待比较数值大的情况下继续循环比较,直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。
值得注意的是,我们必需用一个存储空间来保存当前待比较的数值,因为当一趟比较完成时,我们要将待比较数值置入比它小的数值的后一位 插入排序类似玩牌时整理手中纸牌的过程。插入排序的基本方法是:每步将一个待排序的记录按其关键字的大小插到前面已经排序的序列中的适当位置,直到全部记录插入完毕为止。

代码实现

 1 static void Main(string[] args)
 2         {
 3             int[] arry = new int[] { 3, 5, 7, 4, 1, 0, -2, -1, 7, 3 };
 4             arry = InsertSort(arry);
 5             foreach (var item in arry)
 6             {
 7                 Console.Write("\t" + item);
 8             }
 9             Console.ReadKey();
10         }
11         public static int[] InsertSort(int[] arry)
12         {
13             for (int i = 1; i < arry.Length; i++)
14             {
15                 //需要插入
16                 if (arry[i] < arry[i - 1])
17                 {
18                     int temp = arry[i];
19                     int j;
20                     //循环比较i-1次,满足条件,说明要被交换
21                     for (j = i - 1; j >= 0 && temp < arry[j]; j--)
22                     {
23                         //
24                         arry[j + 1] = arry[j];
25                     }
26                     //由于最后一次j又--了,所有这里加1
27                     arry[j + 1] = temp;
28                     //第二种交换方法,从头开始遍历,如果有值大于要插入的值,那么两个值进行交换,并将temp重新赋值为遍历到的值
29                     //for (j = 0; j < i; j++)
30                     //{
31                     //    if (temp < arry[j])
32                     //        {
33                     //            将temp重新赋值为遍历到的值
34                     //            temp = arry[j];
35                     //            arry[j] = arry[i];
36                     //            arry[i] = temp;
37                     //        }
38                     //}
39                 }
40             }
41             return arry;
42         }

希尔排序:

希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因DL.Shell于1959年提出而得名。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。
但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

基本思想

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量 =1( < …<d2<d1),即所有记录放在同一组中进行直接插入排序为止。
该方法实质上是一种分组插入方法
比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比[2] 较就可能消除多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。
一般的初次取序列的一半为增量,以后每次减半,直到增量为1。

代码实现

 1 static void Main(string[] args)
 2         {
 3             int[] arry = new int[] { 57, 68, 59, 52, 72, 28, 96, 33, 24, 19, 19, 68 ,-12};
 4             arry = ShellSort(arry);
 5             foreach (var item in arry)
 6             {
 7                 Console.Write("\t" + item);
 8             }
 9             Console.ReadKey();
10         }
11
12
13         public static int[] ShellSort(int[] arry)
14         {
15             int length = arry.Length;
16             for (int d = (int)Math.Ceiling(length/2.0); d > 0; d=(int)Math.Ceiling(d/2.0))
17             {
18                 //直接插入法
19                 for (int i = d; i < arry.Length; i++)
20                 {
21                     int temp=arry[i];
22                     //需要插入。改变位置
23                     if (temp < arry[i - d])
24                     {
25                         for (int j = i-d; j < i; j += d)
26                         {
27                             if (temp < arry[j])
28                             {
29                                 temp = arry[j];
30                                 arry[j] = arry[i];
31                                 arry[i] = temp;
32                             }
33                         }
34                     }
35                 }
36                 if (d == 1)
37                     break;
38             }
39             return arry;
40         }

直接选择排序:

设所排序序列的记录个数为n。i取1,2,…,n-1,从所有n-i+1个记录(Ri,Ri+1,…,Rn)中找出排序码最小的记录,与第i个记录交换。执行n-1趟 后就完成了记录序列的排序。

在简单选择排序过程中,所需移动记录的次数比较少。最好情况下,即待排序记录初始状态就已经是正序排列了,则不需要移动记录。
最坏情况下,即待排序记录初始状态是按逆序排列的,则需要移动记录的次数最多为3(n-1)。简单选择排序过程中需要进行的比较次数与初始状态下待排序的记录序列的排列情况无关。当i=1时,需进行n-1次比较;当i=2时,需进行n-2次比较;依次类推,共需要进行的比较次数是(n-1)+(n-2)+…+2+1=n(n-1)/2,即进行比较操作的时间复杂度为O(n^2),进行移动操作的时间复杂度为O(n)。

代码实现

 1  static void Main(string[] args)
 2         {
 3             int[] arry = new int[] { 57, 68, 59, 52, 72, 28, 96, 33, 24, 19, 68, -12 };
 4             arry = DirectSelectSort(arry);
 5             foreach (var item in arry)
 6             {
 7                 Console.Write("\t" + item);
 8             }
 9             Console.ReadKey();
10         }
11
12         public static int[] DirectSelectSort(int[] arry)
13         {
14             //最小数的下标
15             int minKey;
16             int temp;
17             for (int i = 0; i < arry.Length; i++)
18             {
19                 minKey = i;
20                 for (int j = i+1; j < arry.Length; j++)
21                 {
22                     if (arry[minKey] > arry[j])
23                         minKey = j;
24                 }
25                 temp = arry[minKey];
26                 arry[minKey] = arry[i];
27                 arry[i] = temp;
28             }
29             return arry;
30         }

冒泡排序:

已知一组无序数据a[1]、a[2]、……a[n],需将其按升序排列。首先比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。再比较a[2]与a[3]的值,若a[2]大于a[3]则交换两者的值,否则不变。再比较a[3]与a[4],以此类推,最后比较a[n-1]与a[n]的值。这样处理一轮后,a[n]的值一定是这组数据中最大的。再对a[1]~a[n-1]以相同方法处理一轮,则a[n-1]的值一定是a[1]~a[n-1]中最大的。再对a[1]~a[n-2]以相同方法处理一轮,以此类推。共处理n-1轮后a[1]、a[2]、……a[n]就以升序排列了。降序排列与升序排列相类似,若a[1]小于a[2]则交换两者的值,否则不变,后面以此类推。 总的来讲,每一轮排序后最大(或最小)的数将移动到数据序列的最后,理论上总共要进行n(n-1)/2次交换。

代码实现

 1  static void Main(string[] args)
 2         {
 3             int[] arry = new int[] { 1,3,4,2,6,-2};
 4             BubbleSort(ref arry);
 5             foreach (var item in arry)
 6             {
 7                 Console.Write("\t"+item);
 8             }
 9             Console.ReadKey();
10         }
11         public static void BubbleSort(ref int[] arry)
12         {
13             for (int i = 0; i < arry.Length; i++)
14             {
15                 for (int j = 0; j < arry.Length-1-i; j++)
16                 {
17                     if (arry[j] > arry[j + 1])
18                     {
19                         int temp = arry[j + 1];
20                         arry[j + 1] = arry[j];
21                         arry[j] = temp;
22                     }
23                 }
24             }
25         }

快速排序:

设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j–),找到第一个小于key的值A[j],将A[j]和A[i]互换;
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]和A[j]互换;
5)重复第3、4步,直到i=j; (3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。找到符合条件的值,进行交换的时候i, j指针位置不变。另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。

代码实现

 1   static void Main(string[] args)
 2         {
 3             int[] arry = new int[] { 1,3,4,2,6,-2,7,1};
 4             arry = QuickSort(arry,0,arry.Length-1);
 5             foreach (var item in arry)
 6             {
 7                 Console.Write("\t"+item);
 8             }
 9             Console.ReadKey();
10         }
11         /// <summary>
12         /// 快速排序算法
13         /// </summary>
14         /// <param name="arry"></param>
15         /// <param name="left">低位</param>
16         /// <param name="right">高位</param>
17         public static int[] QuickSort(int[] arry, int left, int right)
18         {
19             if (left < right)
20             {
21                 //选基准
22                 int middle = arry[(left + right) / 2];
23                 int i = left - 1;
24                 int j = right + 1;
25                 while (true)
26                 {
27                     //从左往右直到找到一个值大于基准
28                     while (arry[++i] < middle && i < right) ;
29                     //从右往左直到找到一个值小于基准
30                     while (arry[--j] > middle && j > left) ;
31                     if (i >= j)
32                         break;
33                     //交换
34                     int temp = arry[i];
35                     arry[i] = arry[j];
36                     arry[j] = temp;
37                 }
38                 //递归
39                 QuickSort(arry, left, i - 1);
40                 QuickSort(arry,j+1,right);
41             }
42             return arry;
43         }

堆排序:

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。堆分为大根堆和小根堆,是完全二叉树。大根堆的要求是每个节点的值都不大于其父节点的值,即A[PARENT[i]] >= A[i]。在数组的非降序排序中,需要使用的就是大根堆,因为根据大根堆的要求可知,最大的值一定在堆顶。

代码实现

 1 static void Main(string[] args)
 2         {
 3             int[] arry = new int[] { 34,12,32,2,54,6,23,-4,2,0,7,-9};
 4             arry=HeapSort(arry,arry.Length);
 5             foreach (var item in arry)
 6             {
 7                 Console.Write("\t"+item);
 8             }
 9             Console.ReadKey();
10         }
11
12         public static int[] HeapSort(int[] arry, int top)
13         {
14             List<int> topNode = new List<int>();
15
16             for (int i = arry.Length / 2 - 1; i >= 0; i--)
17             {
18                 HeapAdjust(arry, i, arry.Length);
19             }
20
21             for (int i = arry.Length - 1; i >= arry.Length - top; i--)
22             {
23                 int temp = arry[0];
24                 arry[0] = arry[i];
25                 arry[i] = temp;
26                 HeapAdjust(arry, 0, i);
27             }
28             return arry;
29         }
30         /// <summary>
31         /// 构建堆
32         /// </summary>
33         /// <param name="arry"></param>
34         /// <param name="parent"></param>
35         /// <param name="length"></param>
36         private static void HeapAdjust(int[] arry, int parent, int length)
37         {
38             int temp = arry[parent];
39
40             int child = 2 * parent + 1;
41
42             while (child < length)
43             {
44                 if (child + 1 < length && arry[child] < arry[child + 1]) child++;
45
46                 if (temp >= arry[child])
47                     break;
48
49                 arry[parent] = arry[child];
50
51                 parent = child;
52
53                 child = 2 * parent + 1;
54             }
55
56             arry[parent] = temp;
57         }

堆排序算法的实现是看别人博客的内容。

另外的归并排序和基数排序考的不多,就不写了。

时间: 2024-10-12 09:10:09

软考笔记第六天之各排序算法的实现的相关文章

探讨排序算法的实现

排序算法是我们工作中使用最普遍的算法,常见的语言库中基本都会有排序算法的实现,比如c标准库的qsort,stl的sort函数等.本文首先介绍直接插入排序,归并排序,堆排序,快速排序和基数排序等比较排序算法,然后介绍计数排序,基数排序等具有线性时间的排序算法.本文主要讨论算法的实现方法,并不会过多介绍基本理论. 评价一个排序算法优劣适用与否,一般需要从三个方面来分析 时间复杂度.用比较操作和移动操作数的最高次项表示,由于在实际应用中最在乎的是运行时间的上限,所以一般取输入最坏情况的下的运行时间作为

Python 排序算法的实现

冒泡排序: 1 def bubble(l): 2 length = len(l) 3 for i in range(length): 4 for j in range(i+1, length): 5 if l[i] > l[j]: 6 l[i], l[j] = l[j], l[i] 7 print l 选择排序: 1 def select(l): 2 length = len(l) 3 for i in range(length): 4 minn = i 5 for j in range(i+1

Python学习(三) 八大排序算法的实现(下)

本文Python实现了插入排序.基数排序.希尔排序.冒泡排序.高速排序.直接选择排序.堆排序.归并排序的后面四种. 上篇:Python学习(三) 八大排序算法的实现(上) 1.高速排序 描写叙述 通过一趟排序将要排序的数据切割成独立的两部分,当中一部分的全部数据都比另外一部分的全部数据都要小,然后再按此方法对这两部分数据分别进行高速排序,整个排序过程能够递归进行,以此达到整个数据变成有序序列. 1.先从数列中取出一个数作为基准数. 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全

七种排序算法的实现和总结

最近把七种排序算法集中在一起写了一遍. 注释里有比较详细的说明. 1 /*排序算法大集合**/ 2 #include <stdio.h> 3 #include <string.h> 4 #include <stdlib.h> 5 6 //------------------快速排序------------------// 7 /* 8 核心: 9 如果你知道多少人该站你前面,多少人站你后面,你一定知道你该站哪个位置. 10 算法: 11 1.选取分界数,参考这个分界数,

软考笔记之存储管理

软考随堂笔记 考点1 实存管理 考点2 虚存管理 程序的装入(重定位)(将逻辑地址转换成物理地址) 静态重定位:静态重定位是在虚空间程序执行之前由装配程序完成地址影射工作. 动态重定位:动态重定位是在程序执行过程中,在CPU访问内存之前,将要访问的程序或数据地址转换为内存地址. 实存管理 存储管理的任务是存储空间的分配与回收.在现代操作系统中通常有单一连续分配(静态).固定分区分配(静态).可变分区分配(动态)三种分配方式: 单一连续分配(静态):不分区,所有用户空间给某个进程或作业.同一时间只

常见排序算法的实现(归并排序、快速排序、堆排序、选择排序、插入排序、希尔排序)

这篇博客主要实现一些常见的排序算法.例如: //冒泡排序 //选择排序 //简单插入排序 //折半插入排序 //希尔排序 //归并排序 //双向的快速排序 //单向的快速排序 //堆排序 对于各个算法的实现原理,这里不再多说了,代码中注释较多,结合注释应该都能理解算法的原理,读者也可自己google一下.另外,注释中有很多点,比如边界条件.应用场景等已经用 * 标记,* 越多,越应该多注意. 下面是实现: //冒泡排序 void BubbleSort(int *arr, int n) { if(

软考笔记第一天之数制

  数值1 数值-1 1-1 原码 0000 0001 1000 0001 1000 0010(-2) 反码 0000 0001 1111 1110 1111 1111(-0) 补码 0000 0001 1111 1111 0000 0000(0) 移码 0000 0001 0111 1111 1000 0000 反码(针对于负数):原码符号位不变,其余各位取反; 补码(针对于负数):反码基础上加1; 移码(针对于负数):补码基础上,符号位取反,其余各位不变. 在1-1的运算过程中,原码得到的结

计算机软考笔记之《数据结构与算法》

1.线性结构 (1)线性表 ①线性表的定义 ②线性表的存储结构 ③线性表的应用 (2)栈和队列 ①栈 ②队列 (3)串 ①串的定义及基本运算 ②串的存储结构 2.数组和矩阵 (1)数组 (2)矩阵 3.树和图 (1)树 ①树的定义 ②二叉树的定义和基本运算 ③二叉树的性质 ④二叉树的存储结构 ⑤二叉树的遍历 ⑥最优二叉树 ⑦二叉查找树 (2)图 ①图的定义及术语 ②图的存储结构 4.常用算法 (1)算法概述 ①算法的基本概念 ②算法与数据结构 ③算法的描述 ④算法效率 (2)排序算法 ①排序的基

软考笔记第九天之多媒体基础

内容: 多媒体技术基础概念 多媒体相关计算问题 常见多媒体标准 数据压缩技术 声音的带宽: 人耳:20Hz-20kHz 说话:300-3400Hz 乐器:20Hz-20kHz 采样:采样频率,采样精度 奈奎斯特:采样频率应为声音最高频率的2倍 彩色空间:RGB(电脑),YUV(电视,兼容[黑白电视和彩色电视,Y:亮度信号,U,V颜色偏移量]),CMY(CMYK,K:黑色)(印刷),HSV(HSB)(艺术家空间) 电视上还是用YIQ,YCbCr的彩色空间 媒体的种类: 感觉媒体:指人们接触信息的感