C#数据结构与算法揭秘17

简介:

这节我们介绍直接插入排序和希尔排序算法,

一、直接插入排序

直接插入排序(direct Insert Sort)的基本思想是:顺序地将待排序的记录按其关键码的大小插入到已排序的记录子序列的适当位置。 子序列的记录个数从1开始逐渐增大,当子序列的记录个数与顺序表中的记录个数相同时排序完毕。

设待排序的顺序表 sqList 中有 n 个记录,初始时子序列中只有一个记录sqList[0]。第一次排序时,准备把记录 sqList[1]插入到已排好序的子序列中,这时只需要比较 sqList[0]和 sqList[1]的大小,若 sqList[0]≤sqList[1],说明序列已有序,否则将 sqList[1]插入到 sqList[0]的前面,这样子序列的大小增大为 2。第二次排序时,准备把记录 sqList[2]插入到已排好序的子序列中,这需要先比较 sqList[2] 和 sqList[1]以确定是否需要把 sqList[2]插入到sqList[1]之前。如果 sqList[2]插入到 sqList[1]之前,再比较 sqList[2]和sqList[0]以确定是否需要把 sqList[2]插入到 sqList[0]之前。 这样的过程一直进行到 sqList[n-1]插入到子序列中为止。这时,顺序表 sqList 就是有序的。如图所示:

直接插入排序的算法如下所示,算法中记录的比较表示记录关键码的比较,顺序表中只存放了记录的关键码:相应源代码如下:


//排序的插入排序的算法
public void InsertSort(SeqList<int> sqList) 
    { 
       //  从头开始遍历
          for (int i = 1; i < sqList.Last; ++i) 
          { 
               if (sqList[i] < sqList[i - 1]) 
               { 
                    //取数值较小的
                    int tmp = sqList[i]; 
                     //取首先的值
                     int j = 0; 
                    for (j = i - 1; j >= 0&&tmp<sqList[j]; --j) 
                    { 
                        sqList[j + 1] = sqList[j]; 
                    } 
                       //进行赋值
                    sqList[j + 1] = tmp; 
                }
        } 
 }
//双层循环,时间的复杂度是O(n2)

(1) 最好的情况是顺序表中的记录已全部排好序。这时外层循环的次数为n-1,内层循环的次数为 0。这样,外层循环中每次记录的比较次数为 1,所以直接插入排序算法在最好情况下的时间复杂度为 O(n)。
(2) 最坏情况是顺序表中记录是反序的。这时内层循环的循环系数每次均为 i。因此,直接插入排序算法在最坏情况下的时间复杂度为O(n2)。 

(3) 如果顺序表中的记录的排列是随机的,则记录的期望比较次数为n2/4。因此,直接插入排序算法在一般情况下的时间复杂度为O(n2)。 可以证明,顺序表中的记录越接近于有序,直接插入排序算法的时间效率越高,其时间效率在O(n)到O(n2)之间。
直接插入排序算法的空间复杂度为 O(1)。因此,直接插入排序算法是一种稳定的排序算法。什么是稳定的排序算法,就是前面与后面的数字相等的话,不用交换。

二、希尔排序

希尔排序又叫缩小增量法,属于插入类排序,是将整个无序列分割成若干小的子序列分别进行插入排序。排序过程:先取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序;然后取d2<d1,重复上述分组和排序操作;直至di=1,即所有记录放进一个组中排序为止。

 

 相应的源代码如下:


/// <summary>
        /// Shell Sort
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="array"></param>
        public static void ShellSort<T>(T[] array) where T : IComparable
        {
                //长度
            int length = array.Length;
            for (int h = length / 2; h > 0; h = h / 2)
            {
                //here is insert sort
                for (int i = h; i < length; i++)
                {
                    T temp = array[i];
//  进行 渐变的  变量比较
                    if (temp.CompareTo(array[i -h]) < 0)
                    {
                        for (int j = 0; j < i; j += h)
                        {
                             //变量交换
                            if (temp.CompareTo(array[j]) < 0)
                            {
                                temp = array[j];
                                array[j] = array[i];
                                array[i] = temp;
                            }
                        }
                    }
                }
            }
        }
//算法的时间复杂度是O(n2)

 由于是三层循环,时间复杂度是O(n3);这是一个不稳定的排序。
这节,我们介绍了直接插入排序和希尔排序。下节我们介绍,基数排序 ,简单选择排序 ,堆排序。


目录
相关文章
|
1月前
|
开发框架 算法 搜索推荐
C# .NET面试系列九:常见的算法
#### 1. 求质数 ```c# // 判断一个数是否为质数的方法 public static bool IsPrime(int number) { if (number < 2) { return false; } for (int i = 2; i <= Math.Sqrt(number); i++) { if (number % i == 0) { return false; } } return true; } class Progr
58 1
|
4月前
|
搜索推荐 算法 C#
【Unity 3D】C#中冒泡排序、选择排序、插入排序等算法的详解(附源码 超详细)
【Unity 3D】C#中冒泡排序、选择排序、插入排序等算法的详解(附源码 超详细)
46 1
|
4月前
|
机器学习/深度学习 算法 C#
C# | 凸包算法之Andrew‘s,获取围绕一组点的凸多边形的轮廓点
这篇关于凸包算法的文章,本文使用C#和Andrew’s算法来实现凸包算法。 首先消除两个最基本的问题: 什么是凸包呢? 凸包是一个包围一组点的凸多边形。凸多边形是指多边形中的每个内角都小于180度的多边形。 凸包算法有什么用呢? 凸包算法的作用是找到这个凸多边形,并且使用最少的点来绘制出它的轮廓。凸包算法在计算机图形学、计算几何和机器学习等领域中有着广泛的应用。
50 0
|
1月前
|
搜索推荐 C#
C#实现冒泡排序算法
C#实现冒泡排序算法
18 0
|
3月前
|
算法 C#
C# .Net Core bytes转换为GB/MB/KB 算法
C# .Net Core bytes转换为GB/MB/KB 算法
34 0
|
4月前
|
存储 算法 数据处理
C# | 上位机开发新手指南(十一)压缩算法
流式压缩 流式压缩是一种能够实时处理数据流的压缩方式,例如音频、视频等实时传输的数据。 通过流式压缩算法,我们可以边读取边压缩数据,并能够随时输出已压缩的数据,以确保数据的实时性和减少存储和传输所需的带宽。 块压缩 块压缩则是将数据划分为固定大小的块,在每个块内进行独立的压缩处理。块压缩通常适用于文件、存储、传输等离线数据处理场景。 字典压缩 字典压缩是一种基于字典的压缩算法,通过建立一个字典来存储一组重复出现的字符串,并将这些字符串替换成字典中相应的索引,从而减少数据的存储和传输。字典压缩算法可以更好地处理数据中的重复模式,因为它们可以通过建立字典来存储和恢复重复出现的字符串。
44 0
C# | 上位机开发新手指南(十一)压缩算法
|
4月前
|
算法 C# 数据安全/隐私保护
C# | 上位机开发新手指南(十)加密算法——ECC
本篇文章我们将继续探讨另一种非对称加密算法——ECC。 严格的说,其实ECC并不是一种非对称加密算法,它是一种基于椭圆曲线的加密算法,广泛用于数字签名和密钥协商。 与传统的非对称加密算法(例如RSA)不同,ECC算法使用椭圆曲线上的点乘法来生成密钥对和进行加密操作,而不是使用大数分解等数学算法。这使得ECC算法具有相同的安全性和强度,但使用更少的位数,因此在资源受限的环境中具有优势。 ECC算法虽然使用公钥和私钥进行加密和解密操作,但是这些操作是基于点乘法实现的,而不是基于大数分解等算法实现的。因此,ECC算法可以被视为一种非对称加密算法的变体,但是它与传统的非对称加密算法有所不同。
130 0
C# | 上位机开发新手指南(十)加密算法——ECC
|
4月前
|
XML 算法 安全
C# | 上位机开发新手指南(九)加密算法——RSA
RSA的特性 非对称性 RSA算法使用公钥和私钥两个不同的密钥,公钥用于加密数据,私钥用于解密数据。公钥可以公开,任何人都可以使用,而私钥只有密钥持有人可以访问。 安全性 RSA算法基于大数分解难题,即将一个大的合数分解成其质数因子的乘积。由于目前没有有效的算法可以在合理的时间内对大质数进行分解,因此RSA算法被认为是一种安全的加密算法。 可逆性 RSA算法既可以用于加密,也可以用于解密。加密和解密都是可逆的过程,只要使用正确的密钥,就可以还原原始数据。 签名 RSA算法可以用于数字签名,用于验证数据的完整性和真实性。签名过程是将数据使用私钥进行加密,验证过程是将签名使用公钥进行解密。
101 0
C# | 上位机开发新手指南(九)加密算法——RSA
|
4月前
|
算法 搜索推荐 安全
C# | 上位机开发新手指南(八)加密算法——AES
AES——这是在加密算法中相当重要的一种加密方式! 虽然这个世界上已经存在了非对称加密算法(比如RSA、ECC等),但是在对称加密算法中,AES的地位依然相当重要。与非对称加密算法不同,对称加密算法使用的是相同的密钥对数据进行加密和解密,因此其加密和解密速度更快,而且更加高效。而在对称加密算法中,AES是目前最安全、最可靠的加密算法之一,其加密强度和运行效率都非常高。因此,无论是在个人计算机、移动设备,还是在服务器和云计算等领域,AES都被广泛应用于数据的加密和解密过程中。
93 0
C# | 上位机开发新手指南(八)加密算法——AES
|
4月前
|
存储 算法 安全
C# | 上位机开发新手指南(七)加密算法
加密算法是信息安全领域中的重要技术之一,可以保护数据在传输、存储和处理过程中的安全性。 学习加密算法可以帮助我们更好地理解和应用其他相关技术。例如,数字证书、数字签名、安全协议等都与加密算法密切相关,掌握加密算法可以为我们理解和应用这些技术提供帮助。
54 0
C# | 上位机开发新手指南(七)加密算法