zoukankan      html  css  js  c++  java
  • 排序

        排序是一种非常常见,最基本的算法之一。常见的比较排序算法有以下四种:

    1.插入排序

       插入排序又分为直接插入排序和希尔排序。直接插入排序,指的是每次从序列中取出一个元素把它插入有序表中的合适的位置,使新的有序表仍然有序。具体方法是第一趟先比较前两个数,然后把第二个数插入到有序表中,第二趟把第三个数据插入有序表中,是有序表仍然有序。。。进行了(n-1)次插入,有序表完成排序。代码实现如下:

    void Insertsort(int *a, size_t size)
    {
    assert(a);
    for (int i = 1; i < size; ++i)
    {
    int index = i;
    int tmp = a[index];
    int end = index - 1;
    while (end >= 0 && tmp < a[end])
    {
    a[end + 1] = a[end];
    --end ;
    a[end + 1] = tmp;
    }
    }
    }

        希尔排序实际上是一种分组插入的方法,是直接插入法的一种更高效的改进版本。其思想是:先取一个小于n的增量gap,把所有距离为gap的倍数的记录放在同一个组中,进行直接插入排序,然后再取第二个增量。其代码实现如下:

    void shellsort(int *a,size_t size)
    {
    assert(a);
    int gap = size;
    while (gap > 1)
    {
    gap = gap / 3 + 1;
    }
    for (int i = gap; i < size; ++i)
    {
    int index = i;
    int tmp = a[index];
    int end = index - gap;
    while (end >= 0 && tmp < a[end])
    {
    a[end + gap] = a[end];
    end -= gap;
    a[end + gap] = tmp;
    }
    }
    }

    2.选择排序

        堆排序是一种特殊的选择排序,并且借助了堆特点。其代码实现如下:

    void AdjustDown(int *a, size_t size, int root)
    {
    assert(a);
    int child = root * 2 + 1;
    while (child <size)
    {
    if (child + 1 < size&&a[child + 1] < a[child])
    {
    ++child;
    }
    if (a[child] < a[root])
    {
    std::swap(a[child], a[root]);
    root=child;
    child=root*2+1;
    }
    else
    {
    break;
    }
    }
    }

    void Heapsort(int *a,size_t size)
    {
    assert(a);
    for (int i = (size - 2) / 2; i >= 0; --i)
    {
    AdjustDown(a, size, i);
    }
    for (int i = 0; i < size ; ++i)
    {
    std::swap(a[0], a[size - 1 - i]);
    AdjustDown(a,size-1-i,0);
    }

    }

        注意,在这里AdjustDown是建大堆,排序的结果为降序,还有一种方法为建小堆AdjustDown,排序结果为升序,其代码实现如下:

    void AdjustUp(int *a, size_t size, int child)
    {
    assert(a);
    int root = (child - 1) / 2;
    while (child >0)
    {
    if (a[child] > a[root])
    {
    std::swap(a[child], a[root]);
    child=root;
    root=(child-1)/2;
    }
    else
    {
    break;
    }
    }
    }

    3.交换排序

         交换排序中冒泡排序,快速排序是应用最多的。冒泡排序的思想是:从第一对数据开始直到最后一对数据,比较他们的大小,如果第一个比第二个大就交换他们。。这样排下来,最后一个数就是最大的。剩下的所有元素也按这样排,  直到没有数据可以排时,排序完成。其代码实现如下:

    void Bubblesort(int *a, int n)
    {
    assert(a);
    for (int j = 0; j < 9; ++j)
    {
    for (int i = 0; i < 9 - j; ++i)
    {
    if (a[i]>a[i + 1])
    {
    int t = a[i];
    a[i] = a[i + 1];
    a[i + 1] = t;
    }
    }
    }
    }

       快速排序是实际应用中最常见的一种算法,速度快效率高。快速排序是最优秀的排序算法。一般的实现方法如下:

    void quicksort(int *a,int left,int right)
    {
    assert(a);
    int tmp = a[left];

    int i = left;
    int j = right;
    if (left > right)
    {
    return;
    }
    while (i != j)
    {
    while (a[j] >= tmp&&i < j)
    {
    j--;
    }
    while (a[i] <= tmp&&i < j)
    {
    i++;
    }

    if (i < j)
    {
    int t = a[i];
    a[i] = a[j];
    a[j] = t;
    }
    }

    a[left] = a[i];
    a[i] = tmp;

    quicksort(a,left, i - 1);
    quicksort(a,i + 1, right);
    }

      这样的快速排序运行起来结果正确,但是还是不严谨,比如当给定数组的最后一个数就是整个数组中最大数时,程序运行的结果就出现错误。下次单独介绍。

    4.归并排序

       归并排序是采用分治法的一个典型的例子,即把待排序的序列分为若干个有序的子序列,再把子序列合并成一个整体有序的序列。其代码实现如下:

    void mergeSection(int *a, int *temp, int begin1, int end1, int begin2, int end2)
    {
    int index = begin1;
    while (begin1 <= end1&&begin2 <= end2)
    {
    if (a[begin1] < a[begin2])
    {
    temp[index++] = a[begin1++];
    }
    else
    {
    temp[index++] = a[begin2++];
    }
    }
    while (begin1 <= end1)
    {
    temp[index++] = a[begin1++];
    }
    while (begin2 <= end2)
    {
    temp[index++] = a[begin2++];
    }
    }
    void _mergesort(int *a, int *temp, int left, int right)
    {
    assert(a);
    if (left < right)
    {
    int mid = left + (right - left) / 2;
    _mergesort(a, temp, left, mid);
    _mergesort(a, temp, mid + 1, right);
    mergeSection(a, temp, left, mid, mid + 1, right);
    memcpy(a + left, temp + left, sizeof(int)*(right - left + 1));
    }
    }

    void mergesort(int *a, size_t size)
    {
    int *temp = new int[size];
    _mergesort(a, temp, 0, size - 1);
    delete[] temp;
    }

  • 相关阅读:
    找水王
    环状二维数组最大子数组和
    用户模板
    课堂作业-电梯调度
    书店折扣问题
    《软件工程》读后感
    首尾相连的二维数组最大子数组求和
    梦断代码读后感(二)
    返回一个整数数组中最大子数组的和之测试
    首尾相连的一位数组最大子数组和
  • 原文地址:https://www.cnblogs.com/qingjiaowoxiaoxioashou/p/5372959.html
Copyright © 2011-2022 走看看