数据结构与算法C#版笔记--排序(Sort)-上

简介: 这里讨论的仅限于内部排序(即全部数据都在内存中,通过CPU运算处理元素排序),而且仅限顺序表排序(即不讨论链表,树状结构等结构的排序) 注:排序后的结果可以从小到大,或者从大到小,这只是一个相反的处理而已,为方便起见,本文中的方法都是从小到大排序 1、直接插入排序(InsertOrder) 思...

这里讨论的仅限于内部排序(即全部数据都在内存中,通过CPU运算处理元素排序),而且仅限顺序表排序(即不讨论链表,树状结构等结构的排序)

注:排序后的结果可以从小到大,或者从大到小,这只是一个相反的处理而已,为方便起见,本文中的方法都是从小到大排序

1、直接插入排序(InsertOrder)

思路:从第二个元素开始向后遍历,检查本身(后面称之为tmp)与前面相邻元素的大小,如果发现前面的元素更大,则依次从近及远(即倒序遍历)检查前面的所有元素,将比自身元素大的元素依次后移,这样最终将得到一个空位,将tmp元素插在这个位置即可.

        /// <summary>
        /// 直接插入排序法
        /// </summary>
        /// <param name="lst"></param>
        static void InsertSort(int[] lst)
        {
            int _circleCount = 0;
            //外循环从第二个元素开始从前向后遍历
            for (int i = 1; i < lst.Length; i++)
            {
                _circleCount++;
                //Console.WriteLine("外循环i=" + i);
                //如果发现某元素比前一个元素小
                if (lst[i] < lst[i - 1])
                {
                    int tmp = lst[i];
                    int j = 0;
                    //则该元素前面的元素,从后到前遍历,依次后移,直接找到应该插入的空档在哪里(这样tmp元素就找到了自己的位置)
                    for (j = i - 1; j >= 0 && tmp < lst[j]; j--)
                    {
                        //如果发现有比tmp小的元素,则将元素后移一位(从而把自身空出来,形成一个空档,以方便如果前面还有更小的元素时,可以继续向后面的空档移动)
                        lst[j + 1] = lst[j];
                        _circleCount++;
                        //Console.WriteLine("内循环i=" + i + ",内循环j=" + j);
                    }
                    //Console.WriteLine("j={0}", j);
                    //运行到这里时,j已经是空档的前一个下标
                    lst[j + 1] = tmp;
                }
            }
            Console.WriteLine("InsertOrder共循环了{0}次", _circleCount);
        }

点评:最好情况下,如果所有元素(N个)已经排好序了,则外循环跑N-1次,内循环一次也进不了,即0次,时间复杂度为O(N);最坏情况下,所有元素反序,外循环N-1次,内循环为i(i从1到N-1),时间复杂度为O(N*N);所以元素越有序列,该方法效率越高,其时间复杂度从O(N)到O(N*N)之间,此外,该方法是一种稳定排序。(注:若数组中有相同值的元素时,经过某方法排序后,这二个相同值的元素先后顺序仍然不变,则称这种排序方法为稳定的,反之为不稳定排序方法)

2、冒泡排序法(BubbleSort)

思路:从最后一个元素开始向前遍历,依次检查本元素与前面相邻元素的大小,如果前面的元素更大,则交换位置,如此反复,直到把自己前移到合适的位置(即 相当于后面的元素,通过这种比较,按照从小到大将不断移动前面来,就象气泡从下面向上冒一样)

        /// <summary>
        /// 冒泡排序法
        /// </summary>
        /// <param name="lst"></param>
        static void BubbleSort(int[] lst)
        {
            int _circleCount = 0;//辅助用,可以去掉

            int tmp;
            for (int i = 0; i < lst.Length; i++)
            {
                for (int j = lst.Length - 2; j >= i; j--)
                {
                    if (lst[j + 1] < lst[j])
                    {
                        tmp = lst[j + 1];
                        lst[j + 1] = lst[j];
                        lst[j] = tmp;
                    }

                    _circleCount++;
                }
            }

            Console.WriteLine("BubbleOrder共循环了{0}次", _circleCount);
        }

点评:与插入排序法类似,最好情况是所有元素已经排好序,这样只跑外循环,内循环因为if判断不成立,直接退出;最坏情况是所有元素反序,外循环和内循环每次都要处理,因此时间复杂度跟插入排序法完全相同,同样这也是一种稳定排序。

3、简单选择排序法 (SimpleSelectOrder)

思路:先扫描整个数组,找出最小的元素,然后跟第一个元素交换(这样,第一个位置的元素就排好了),然后从第二个元素开始继续扫描,找到第二小的元素,跟第二个元素交换(这样,第二个位置的元素也排好了)...如此反复

        /// <summary>
        /// 简单选择排序法
        /// </summary>
        /// <param name="lst"></param>
        static void SimpleSelectSort(int[] lst)
        {
            int _circleCount = 0;//辅助用

            int tmp = 0;
            int t = 0;
            for (int i = 0; i < lst.Length; i++)
            {
                t = i;
                //内循环,找出最小的元素下标
                for (int j = i + 1; j < lst.Length; j++)
                {
                    if (lst[t] > lst[j])
                    {
                        t = j;
                    }
                    _circleCount++;
                }
                //将最小元素[下标为t]与元素i互换
                tmp = lst[i];
                lst[i] = lst[t];
                lst[t] = tmp;
            }
            Console.WriteLine("SimpleSelectSort共循环了{0}次", _circleCount);
        }

点评:跟冒泡法很类似,不过应该注意到,这里的元素交换操作是在内循环外,即不管如何这个交换操作是省不了的,所以其时间复杂度均为O(N*N),同样这也是一个稳定排序。

4、快速排序(QuickOrder)

思路:以数组中间的元素做为分界线(该元素称为支点),扫描其它元素,比支点小的放在左侧,比支点大的放在右侧,这样就把数组分成了二段(即做了一次粗放的大致排序),然后对每一段做同样的处理(即二段变四段,4段变8段...),直到最后每一段只有一个元素为止(没错,该方法是一个递归调用)

        /// <summary>   
        /// 快速排序   
        /// </summary>   
        /// <param name="arr">待排序数组</param>   
        /// <param name="left">数组第一个元素索引Index</param>   
        /// <param name="right">数组最后一个元素索引Index</param>   
        static void QuickSort(int[] arr, int left, int right)
        {
            //左边索引小于右边,则还未排序完成   
            if (left < right)
            {
                //取中间的元素作为比较基准,小于他的往左边移,大于他的往右边移   
                int middle = arr[(left + right) / 2];
                //因为while中要做++与--的操作,所以这里先将i,j各自换外扩张一位
                int i = left - 1;
                int j = right + 1;
                while (true)
                {
                    while (arr[++i] < middle) ;//如果前半部的元素值本身就比支点小,则直接跳过

                    while (arr[--j] > middle) ;//如果后半部的元素值本身就比支点大,则直接跳过

                    //因为前半段是向后遍历,而后半段是向前遍历,所以如果二者碰到了,
                    //则说明所有元素都被扫过了一遍,完成退出
                    if (i >= j) 
                    {
                        break;
                    }

                    //经过前面的处理后,如果发现有放错位置的元素,则将二者对换
                    int tmp = arr[i];
                    arr[j] = arr[i];
                    arr[i] = tmp;

                }

                //经过上面的while循环后,元素已被分成左右二段(左段小于支点,右段大于支点)

                //递归调用,处理左段
                QuickSort(arr, left, i - 1);

                //递归调用,处理右段
                QuickSort(arr, j + 1, right);
            }
        }

点评:每次从中间分成二段,然后再中分为二段,如此反复...这跟二叉树很相似(每次分段,相当于树中的某个节点分成二叉),最好情况下所有元素已经排好序,最终树的左右分支数大致相同(即左右分支长度大致相同),所以分解次数为树的高度log2N,而最坏情况下,所有元素反序,这时分解得到的树相当于一个单右支二叉树(即一个右分支超级长,没有左分支的怪树),即时间复杂度范围为nLog2N 至 N*N。此外,快速排序是一种不稳定的排序(从代码就能看出来,即使是二个相同值的节点,在分段过程中,也有可能被交换顺序)

本来想将堆排序与归并排序一起写在这篇文章里的,今天看了看堆排序,还有点小复杂,完全可以另起一篇详解原理了,下篇将专门学习堆排序及归并排序。

目录
相关文章
|
2月前
|
存储 监控 算法
电脑监控管理中的 C# 哈希表进程资源索引算法
哈希表凭借O(1)查询效率、动态增删性能及低内存开销,适配电脑监控系统对进程资源数据的实时索引需求。通过定制哈希函数与链地址法冲突解决,实现高效进程状态追踪与异常预警。
188 10
|
7月前
|
存储 算法 安全
如何控制上网行为——基于 C# 实现布隆过滤器算法的上网行为管控策略研究与实践解析
在数字化办公生态系统中,企业对员工网络行为的精细化管理已成为保障网络安全、提升组织效能的核心命题。如何在有效防范恶意网站访问、数据泄露风险的同时,避免过度管控对正常业务运作的负面影响,构成了企业网络安全领域的重要研究方向。在此背景下,数据结构与算法作为底层技术支撑,其重要性愈发凸显。本文将以布隆过滤器算法为研究对象,基于 C# 编程语言开展理论分析与工程实践,系统探讨该算法在企业上网行为管理中的应用范式。
227 8
|
8月前
|
机器学习/深度学习 监控 算法
员工上网行为监控软件中基于滑动窗口的C#流量统计算法解析​
在数字化办公环境中,员工上网行为监控软件需要高效处理海量网络请求数据,同时实时识别异常行为(如高频访问非工作网站)。传统的时间序列统计方法因计算复杂度过高,难以满足低延迟需求。本文将介绍一种基于滑动窗口的C#统计算法,通过动态时间窗口管理,实现高效的行为模式分析与流量计数。
246 2
|
6月前
|
监控 算法 数据处理
内网实时监控中的 C# 算法探索:环形缓冲区在实时数据处理中的关键作用
本文探讨了环形缓冲区在内网实时监控中的应用,结合C#实现方案,分析其原理与优势。作为固定长度的循环队列,环形缓冲区通过FIFO机制高效处理高速数据流,具备O(1)时间复杂度的读写操作,降低延迟与内存开销。文章从设计逻辑、代码示例到实际适配效果展开讨论,并展望其与AI结合的潜力,为开发者提供参考。
302 2
|
6月前
|
监控 算法 安全
公司电脑监控软件关键技术探析:C# 环形缓冲区算法的理论与实践
环形缓冲区(Ring Buffer)是企业信息安全管理中电脑监控系统设计的核心数据结构,适用于高并发、高速率与短时有效的多源异构数据处理场景。其通过固定大小的连续内存空间实现闭环存储,具备内存优化、操作高效、数据时效管理和并发支持等优势。文章以C#语言为例,展示了线程安全的环形缓冲区实现,并结合URL访问记录监控应用场景,分析了其在流量削峰、关键数据保护和高性能处理中的适配性。该结构在日志捕获和事件缓冲中表现出色,对提升监控系统效能具有重要价值。
189 1
|
7月前
|
存储 监控 算法
局域网上网记录监控的 C# 基数树算法高效检索方案研究
在企业网络管理与信息安全领域,局域网上网记录监控是维护网络安全、规范网络行为的关键举措。随着企业网络数据量呈指数级增长,如何高效存储和检索上网记录数据成为亟待解决的核心问题。基数树(Trie 树)作为一种独特的数据结构,凭借其在字符串处理方面的卓越性能,为局域网上网记录监控提供了创新的解决方案。本文将深入剖析基数树算法的原理,并通过 C# 语言实现的代码示例,阐述其在局域网上网记录监控场景中的具体应用。
183 7
|
10月前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》图、查找、排序专题考点(含解析)
408考研——《数据结构》图,查找和排序专题考点选择题汇总(含解析)。
796 29
|
11月前
|
存储 人工智能 算法
【C++数据结构——内排序】二路归并排序(头歌实践教学平台习题)【合集】
本关任务是实现二路归并算法,即将两个有序数组合并为一个有序数组。主要内容包括: - **任务描述**:实现二路归并算法。 - **相关知识**: - 二路归并算法的基本概念。 - 算法步骤:通过比较两个有序数组的元素,依次将较小的元素放入新数组中。 - 代码示例(以 C++ 为例)。 - 时间复杂度为 O(m+n),空间复杂度为 O(m+n)。 - **测试说明**:平台会对你编写的代码进行测试,提供输入和输出示例。 - **通关代码**:提供了完整的 C++ 实现代码。 - **测试结果**:展示代码运行后的排序结果。 开始你的任务吧,祝你成功!
386 10
|
11月前
|
搜索推荐 算法 数据处理
【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】
本文介绍了希尔排序算法的实现及相关知识。主要内容包括: - **任务描述**:实现希尔排序算法。 - **相关知识**: - 排序算法基础概念,如稳定性。 - 插入排序的基本思想和步骤。 - 间隔序列(增量序列)的概念及其在希尔排序中的应用。 - 算法的时间复杂度和空间复杂度分析。 - 代码实现技巧,如循环嵌套和索引计算。 - **测试说明**:提供了测试输入和输出示例,帮助验证代码正确性。 - **我的通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了代码运行的测试结果。 通过这些内容,读者可以全面了解希尔排序的原理和实现方法。
274 10
|
11月前
|
搜索推荐 C++
【C++数据结构——内排序】快速排序(头歌实践教学平台习题)【合集】
快速排序是一种高效的排序算法,基于分治策略。它的主要思想是通过选择一个基准元素(pivot),将数组划分成两部分。一部分的元素都小于等于基准元素,另一部分的元素都大于等于基准元素。然后对这两部分分别进行排序,最终使整个数组有序。(第一行是元素个数,第二行是待排序的原始关键字数据。本关任务:实现快速排序算法。开始你的任务吧,祝你成功!
303 7

热门文章

最新文章