美文网首页
经典排序算法我劝你好好理解

经典排序算法我劝你好好理解

作者: 親愛的破小孩 | 来源:发表于2022-02-10 15:13 被阅读0次

冒泡算法

-步骤

-> 比较相邻的元素,如果第一个比第二个大,就交换。
-> 对每一对元素都进行比较,从开始的第一对,到结尾的最后一对。完成后,最后的元素应该是最大的。
-> 针对所有的元素重复上面的步骤,除了最后一个。
-> 持续每次对越来越少的元素重复上面的步骤,直到没有一对数字需要比较。

void BubbleSort(int* h, size_t len)
{
    if(h == NULL) return;
    if(len <= 1) return;
    // i是次数,j是具体下标
    for(int i = 0; i < len - 1; i++)
    {
        for(int j = 0; j < len - 1 - i; j++)
        {
            if(h[j] > h[j+1])
            {
                Swap(h[j], h[j + 1])
            }
        }
    }
}


选择排序

-步骤

-> 在未排序的序列中找到最小(大)的元素,存放到排序序列的最前面。
-> 从剩余未排序的序列中继续寻找最小(大)的元素,然后放到已排序的序列末尾。
-> 重复第二步,直到所有元素均排序完毕。

-理解

选择排序是在未排序的序列里每次去找最大(小)的元素。永远在矮子里面拔高个,被选出来的那一刻,就确定好了自己的位置排名。

void SelectionSort(int* h, size_t len)
{
    if(h == NULL) return;
    if(len <= 1) return;
    int minindex, i, j;
    // i是次数,也即排好的个数,j是继续排
    
    for (i = 0; i < len; i++) // 遍历选到最小的值
    {
        minindex = i;
        // 每轮需要比较的次数是len - i
        for(int j = i + 1; j < len; j++)
        {
            if(h[j] < h[minindex]) minindex = j; // 一轮下来,minindex都是最小的值
        }
        // 将每次找到的最小值都依次放在i位置
        Swap(h(i), h[minindex]); //这样依次排好了前i个数
    }
}

插入排序

-步骤

-> 将待排序的序列的第一个元素看作是一个有序的序列,把第二个元素到最后一个元素的序列看作是一个未排序的序列。
-> 从头到尾依次扫描未排序的序列,将扫描到的每个元素插入到前面有序序列的正确位置。(如果待插入的序列中有与选择的元素相同的元素,那么将这个元素插入到相等元素后面。)

-理解

插入排序是,每一个值都去已经排好队的序列里找自己的位置。
每一个值都不需要等,轮到自己的时候一定会给自己安排上位置,只不过后面还有可能被挤掉就是了。

void InsertSort(int* h, size_t len)
{
    if(h == null) return;
    if( len <= 1) return;
    // 从下标1开始,i代表已经排好序的元素个数
    for (int i = 1; i < len; i++)
    {
        // 用拿到的每一个元素去前面比较,直到找到合适的位置break
        for (int j = i; j > 0; j-- )
        {
            if (h[j] < h[j - 1])
            {
                Swap(h[j], h[j - 1])
            } else
            {
                break;
            }
        }
    }
    return;
}

希尔排序

[理解了过程,但是用代码实现还是有点不熟悉,不理解]

-步骤

-> 选择一个增量序列,t1,t2,...,tk ,其中ti > tj, tk = 1;
-> 按增量序列的个数,对序列进行k趟排序。
-> 每趟排序,根据对应的增量值ti,将待排序序列分割成若干个长度为m的子序列,分别对各子序列进行插入排序,仅增量因子的值为1时,整个序列作为一个表来处理,表的长度即为序列的长度。

-理解

-> 希尔排序采用的是跳跃式的分组策略,通过某个增量,将数组划分为若干组子序列。然后分组进行插入排序,随后逐步缩小增量,继续这个操作,直至增量为1。
-> 这种策略,在初始阶段就可以达到基本有序的程度,然后随着缩小增量,多数情况下后面只要数据微调即可,不会涉及过多数据移动。
-> 我们实现这个算法的时候,使用的增量gap = length/2,缩小增量也以gap/2的方式,这种增量的选择我们可以使用一个序列表示 ,{n/2, (n/2)/2,...,1},这个就是增量序列。增量序列的选择和证明都是个数学难题,我们用的这个增量序列是比较常用的,也是希尔建议的增量,亦称为希尔增量,但其实这个增量不是最优的。

void ShellSort(int* h, size_t len)
{
    if(h == null) return;
    if(len <= 1) return;
    // 增量序列的个数就是对整个序列排序的次数
    // 增量gap,并逐步缩小gap
    for(int div = len/2; div >= 1; div/=2 )
    {
        for(k = 0; k <div; k++)
        {
            for(int i = div + k; i < len; i+=div)
            {
                for(int j = i; j > k; j -= div)
                {
                    if(h[j] < h[j - div]) swap(h[j], h[j - div]);
                    else break;
                }
            }
        }
    }
}

归并排序

-步骤

当我们拿到一个序列的时候:



我们先把它一份为二,像下面这样:



我们现在要做的是分别把左边的和右边的数组进行排序,然后再把两个排好的序列归并在一起。当然我们在分别排一半的序列的时候,也同样使用这种一分为二的方式,这样这个序列又被分成了下面这样:

继续这样的步骤,直到把这个细度分到每个部分只有一个元素为止:



现在每个序列里只有一个元素了,我们用不着排序了,一个元素的序列当然是已经排好序的,现在我们要做的只剩下归并了。
在从一个元素归并到两个元素的过程中,形成了含有两个元素的新序列,我们当然也要让新序列变得有序。

依次类推,我们要继续归并成有四个元素的新序列:

直至最后归并完成:
image.png

现在我们已经直到了这个算法的实现过程 ,但是分序列容易,归并这件事情该如何完成呢?当我们现在有了两个已经排好序的序列时,我们要把它们合并成一个有序的序列,要怎么办效率比较高呢?
这里我们可以申请一块内存,用来存放将要合并好的序列,因为在现代计算机中,时间复杂度是要比空间复杂度要更优先考虑的事情,毕竟内存也好,硬盘也罢,现在是变得越来越能存储了。(这里用了O(n)的额外空间来完成这件事件)
至于在归并过程中使用插入算法还是快速排序那都是很随意的。

这时我们连同额外申请的辅助内存序列外,一共有了三个序列,所以这变成了一个具有三个索引的实现方法。

-理解

归并排序是使用了分治的方法策略,将问题成一个个小的部分然后递归求解,而则是说将的阶段获得的答案拼在一起。分而治之
归并排序可以使用递归的方法实现,也可以用迭代。递归和迭代这两种算法思想也是非常基础和重要的,我会在专门的章节去学习理解。

分的阶段可以采用递归的方法去拆分子序列,递归深度为log2n.
治的阶段则是把两个已经有序的序列进行合并。

相关文章

  • 经典排序算法我劝你好好理解

    冒泡算法 -步骤 -> 比较相邻的元素,如果第一个比第二个大,就交换。-> 对每一对元素都进行比较,从开始的第一对...

  • 算法与数据结构系列 ( 四 ) - 插入排序法- Insert

    前言 本章我们继续理解另外一个排序算法 插入排序插入排序 也算是我们 O(n^2) 的经典排序算法之一插入排序 其...

  • Java冒泡排序,快速排序理解与实现

    经典排序算法中,有好几种排序,下边说下冒泡排序和快速排序的理解与实现,记太多容易混乱; 1.冒泡排序:字面理解,值...

  • 经典排序算法总结

    经典排序算法集锦 冒泡法 排序算法入门之冒泡排序 排序算法入门之冒泡排序优化

  • 用 Python 实现十大经典排序算法

    今天,详细的跟大家分享下 10 种经典排序算法。 10种经典排序算法包括冒泡排序、选择排序、快速排序、归并排序、堆...

  • 序言-算法

    此文集将介绍一些经典的算法,从经典的排序算法开始不定期的补充纠错更新 1、经典排序算法 1.1桶排序Bucket ...

  • 算法学习(1)-排序算法

    八大排序算法九大排序算法再总结[经典排序算法][集锦][直观学习排序算法] 视觉直观感受若干常用排序算法 快速排序...

  • 十大经典排序算法&七大查找算法

    十大经典排序算法: 十大经典排序算法的时间、空间复杂度: 冒泡排序(Bubble Sort) 算法描述: 1、比较...

  • Algorithm -- 排序算法

    单链表十大经典排序算法冒泡排序选择排序插入排序归并排序快速排序堆排序计数排序桶排序 1. 十大经典排序算法 十大经...

  • php之排序-------冒泡排序的优化

    本文需要在理解冒泡排序的基础之上 排序是算法入门的基础操作,冒泡排序很经典。下面这个改进后的冒泡排序,使循环的次数...

网友评论

      本文标题:经典排序算法我劝你好好理解

      本文链接:https://www.haomeiwen.com/subject/pgmnkrtx.html