zoukankan      html  css  js  c++  java
  • 排序算法

      

      终于狠下心来要好好学习下算法了,买了经典名作:算法导论,另外在网易公开课上收看MIT 的 Intorduction to Algorithms,为了正握的更透彻,也为了方便以后复习,把掌握的内容记录下来。

      本期的内容为排序算法(sort algorithms)。

    插入排序(Insertion Sort)

      插入排序正如名字一样好理解。假设需要排序的数组为 array[0...n-1],从数组的第二个数开始,向后进行遍历,每拿到一个数,把这个数插到它前面已经排好序的数组中的适当的位置。这里有一些问题需要说明:

    • 怎样保证前面的数组是有序的?

      从第二个数开始操作,因为它的前面只有一个数,肯定是有序的,插入第二个数后能保证前两个数是有序的。插入第三个数时,前两个数是有序的,把第三个数插入到适当的位置后,保证前三个数是有序的。依次类推,每次插入时,都能保证前面的数是有序的。这个过程的关键是从第二个数开始插入。

    • 插入适当的位置,也就是保证插入后依然是有序的,那么操作过程是怎样的呢?

      这里用个例子来说明。array[5] = {3, 2, 4, 6 1}

           0  1  2  3  4

      begin:     3  2   4      6  1

      step1:     2  3  4  6  1

      step2:   2  3  4  6  1

      step3:   2  3  4  6  1

      step4:   1  2  3  4  6

      橙色的为已经排好序的,绿色的为还未排序的,蓝色加粗的是将要进行插入的数字。从图中可以看到,每次插入时(按升序),假设为array[i],令 j 从 i - 1到0为顺序,直到找出比array[i]小的数。在这个过程中,array[j] = array[j-1],右移数组里的数。找到数之后,将array[i]放在相应的位置。话说的有点混乱,直接上代码。

    void insertionSort(int array[], int n)
    {
        for (int i = 1; i < n; i++)
        {
            int temp = array[i];
            int j = i-1;
            while (j >= 0 && array[j] > temp)
            {
                array[j+1] = array[j];
                j--;
            }
            array[j+1] = temp;
        }
    }

    插入排序是比较慢的排序方法,复杂度为Ο(n2).

    归并排序(Merge Sort)

    归并排序采用分治的思想,分治的思想一般都可以使用递归的方法,归并排序也可以采用递归的方法。

    归并排序思路为:

    1. 将待排序的数组首先分成最小的数组,也就是每个数组只有一个数
    2. 只有一个数的数组是排好序的,然后将排好序的这两个数组进行合并,变成具有两个数的已排好序的数组。
    3. 两个数的排好序的数组再进行合并,最终完成真个数组的排序。

    可以写成伪代码为:

      Merge Sort : array[0....n-1]

    1. If n = 1, done
    2. 递归排序 array[1...(n/2)] 和 array[(n/2)+1, n]
    3. 合并array[1...(n/2)] 和 array[(n/2)+1, n]

    这样看来,这个算法也比较简单了,第三步的合并方法是什么样的呢?其实也不难,不过需要另开辟空间,来存储两个一排好序的数组进行合并后的结果之后再转存到数组A中。依然上代码:

    void merge(int array[], int begin, int mid, int last)
    {
        int left = begin, right = mid + 1;
        int *arrayTemp = (int*)malloc(sizeof(int)*(last-begin+1));//存放结果的临时数组
        int i = 0;
        while (1)
        {
            if (left > mid)//如果左半部分数组全都复制完,将右半部分数组的复制
            {
                while(right<=last)
                {
                    arrayTemp[i++]=array[right++];
                }
                break;
            }
            if (right > last)//如果右半部分数组复制完,将左半部分数组复制
            {
                while(left<=mid)
                {
                    arrayTemp[i++]=array[left++];
                }
                break;
            }
            if (array[left] < array[right])
            {
                arrayTemp[i++] = array[left++];
            }
            else
            {
                arrayTemp[i++] = array[right++];
            }
        }
    
        for (i = 0; i < (last - begin + 1); i++)//将临时数组中的数写会到原数组
        {
            array[begin+i] = arrayTemp[i];
        }
    }
    
    void mergeSort(int array[], int begin, int last)//调用这个函数,begin和last均为下标
    {
        if (begin < last)
        {
            mergeSort(array, begin, (begin+last)/2);
            mergeSort(array, (begin+last)/2 + 1, last);
            merge(array, begin, (begin+last)/2, last);
        }
    }

    归并排序的时间复杂度为Ο(n*log2n).

    作者:viczzx 出处:http://www.cnblogs.com/zixuan-zhang 欢迎转载,也请保留这段声明。谢谢!

  • 相关阅读:
    net core 使用 rabbitmq
    asp.net core WebApi 返回 HttpResponseMessage
    asp.net core 2.1 WebApi 快速入门
    JQuery EasyUI combobox动态添加option
    php截取字符去掉最后一个字符
    JQuery EasyUI Combobox的onChange事件
    对于不返回任何键列信息的 selectcommand 不支持 updatecommand 的动态 sql 生成
    Access2007 操作或事件已被禁用模式阻止解决办法
    Easyui 中 Tabsr的常用方法
    Win 7 IE11不能下载文件,右键另存为也不行
  • 原文地址:https://www.cnblogs.com/zixuan-zhang/p/3330540.html
Copyright © 2011-2022 走看看