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 欢迎转载,也请保留这段声明。谢谢!

  • 相关阅读:
    LOJ#551 Matrix
    洛谷P5163 WD与地图
    洛谷P4831 Scarlet loves WenHuaKe
    LOJ#6118 鬼牌
    支配树
    线性插值
    PropertiesConfiguration
    ThreadLocal
    Thread
    FastJson
  • 原文地址:https://www.cnblogs.com/zixuan-zhang/p/3330540.html
Copyright © 2011-2022 走看看