关于排序

编译器版本:vs2013

排序的目的

::如果输入一系列数字a1,a2,a3,a4,a5,a6,a7
经过排序有
::输出a1< a2< a3< a4< a5< a6< a7或者
::输出a1>a2>a3>a4>a5>a6 >a7
即让一系列无序数字从大到小或者从小到大有序即为排序。

学习中的几种排序算法

1:插入排序
基本思想:
升序:给一个数组,并不知道是否有序,从第二个数开始依次往后直到数组最后一个元素,挨个和前面那个数比大小,大的放这个数后面,小的接着和前面数比,如果比前面每一个数都小,就放在最前面,依次循环比完每一个数。
降序和升序思想一致,只是要把大的放在前面,小的放在后面。

具体代码

void Insertsort(int* a, size_t n)
{
    assert(a);
    for (size_t i = 0; i<n - 1; ++i)
    {
        int end = i;
        int tmp = a[end + 1];
        while (end >= 0)
        {
            if (a[end] > tmp)
            {
                a[end + 1] = a[end];
                --end;
            }
            else
            {
                break;
            }
        }
        a[end + 1] = tmp;
    }
}

给一个整型数组a,数组元素n个,首先assert数组不能为空,空数组不需要排序,
这里写图片描述
i是下标,从0开始,上图中每一个b都是在所画圆圈区域内即将要插入得数,思想在上面已经讲过,就是每一个即将要插入的数和前面的数相比,比前面一个数大就差到那个数后面,找不到要插入的位置就需要一直找,找完已经排序完成的所有数为止,当然,既然是插入,在插入一个新的数以后,排在这个数后面的那些书当然要往后挪一下位置了。

2:希尔排序
希尔排序就是升级版的插入排序,在中间加了一个间距gap,只是为了更快的将前面的大数据和后面的小数据换回来,达到的效果是预排序,
这里写图片描述
假如gap=3,那么就是在这个数组中隔三个数做排序,这样可以尽快把后面的小数据和前面的大数据交换,思想和前面的插入排序一样

void shellsort(int* a, size_t n)
{
    assert(a);
    int gap = 3;
    for (size_t i = 0; i < n - gap; ++i)
    {
        int end = i;
        int tmp = a[end + gap];
        while (end >= 0)
        {
            if (a[end] > tmp)
            {
                a[end + gap] = a[end];
                end -= gap;
            }
            else
            {
                break;
            }
        }
        a[end + gap] = tmp;
    }
}
 end=i;
 tmp=a[end+gap];
 要插入的新元素是tmp,tmp先和前面的a[end]比较,若a[end]大,将a[end]往后挪,end-=gap;再比,知道不满足while或者if条件,a[end + gap] = tmp;完成插入;

3:选择排序
具体思想:升序–给一个无序数组,min和max分别表示数组中最小和最大数的下标,两个都是从0下标开始,找到两个数以后,最小值换到0下标位置,最大值换到n-1下标位置,

void Selectsort(int* a, size_t n)//选下标
{
    assert(a);
    size_t left = 0; 
    size_t right = n - 1;
    while (left < right)
    {
        size_t min = left, max = left;
        for (size_t i = left; i < right; ++i)
        {
            if (a[i]< a[min])
            {
                min = i;
            }
            if (a[i] > a[max])
            {
                max = i;
            }
            swap(a[min], a[left]);
            //9 0 1 2 4 5 7
            //下面这个if条件判断的就是类似上面这类情况,此时min是
            //数组元素0的下标,left是9的下标同时也是数组最大元素9
            //的下标,把0和9交换以后,9的下标即刚才交换之前0的下标
            //而把最小值换到最左边以后需要做的就是把最大值换到最右边
            //最大值现在是9,即a[min],所以需要把max赋值为min和最
            //右边交换,然后--left,--right,在剩下的数里面找最大最
            //小接着上面的操作
            if (max == left)
            {
                max = min;
            }
            swap(a[max], a[right]);
            ++left;
            --right;
        }
    }
}

4:快速排序
具体思想:就是把数组通过多次划分成小区间,甚至这个小区间里面就一个数,把小区间划分排序成有序区间再组合起来就是一个大的有序数组。

int Partsort1(int *a, int left, int right)   //挖坑
{
    int key = a[right];
    int begin = left;
    int end = right;
    while (begin < end)
    {
        while (a[begin] <= key)
        {
            ++begin;
        }
        if (begin < end)
        {
            swap(a[end], a[begin]);
        }
        while (a[end] >= key)
        {
            --end;
        }
        if (begin < end)
        {
            swap(a[begin], a[end]);
        }
    }
    swap(a[begin], a[right]);
    return begin;
}
int Partsort2(int *a,int left,int right)   //左右指针
{
    int key = a[right];
    while (left < right)
    {
        while (left < right&&a[left] <= key)
        {
            ++left;
        }
        a[right] = a[left];
        while (left < right&&a[left] >= key)
        {
            --right;
        }
        a[left] = a[right];
    }
    a[left] = key;
}
int Partsort3(int *a, int left, int right)   //前后指针
{
    int cur = left;
    int key = a[right];
    int prev = left - 1;
    while (cur < right)
    {
        if (a[cur] < a[key] && ++prev != cur)
        {
            swap(a[prev], a[cur]);
        }
        ++cur;
    }
    swap(a[++prev], a[right]);
    return prev;
}
void Quicksort(int *a, int left, int right)
{
    assert(a);
    if (left >= right)
    {
        return;
    }
    else
    {
        int div = Partsort1(a, left, right);
        int div = Partsort2(a, left, right);
        int div = Partsort3(a, left, right);
        Quicksort(a, left, div - 1);
        Quicksort(a, div + 1, right);
    }
}

5:快排非递归实现
具体思想:利用stack先入后出,实现数组划分成小区间,小区间依次排序实现有序并合并以后实现大数组有序。

int Partsort1(int *a, int left, int right)   //挖坑
{
    int key = a[right];
    int begin = left;
    int end = right;
    while (begin < end)
    {
        while (a[begin] <= key)
        {
            ++begin;
        }
        if (begin < end)
        {
            swap(a[end], a[begin]);
        }
        while (a[end] >= key)
        {
            --end;
        }
        if (begin < end)
        {
            swap(a[begin], a[end]);
        }
    }
    swap(a[begin], a[right]);
    return begin;
}
int Partsort2(int *a,int left,int right)   //左右指针
{
    int key = a[right];
    while (left < right)
    {
        while (left < right&&a[left] <= key)
        {
            ++left;
        }
        a[right] = a[left];
        while (left < right&&a[left] >= key)
        {
            --right;
        }
        a[left] = a[right];
    }
    a[left] = key;
}
int Partsort3(int *a, int left, int right)   //前后指针
{
    int cur = left;
    int key = a[right];
    int prev = left - 1;
    while (cur < right)
    {
        if (a[cur] < a[key] && ++prev != cur)
        {
            swap(a[prev], a[cur]);
        }
        ++cur;
    }
    swap(a[++prev], a[right]);
    return prev;
}
void Quicksort(int *a, int left, int right)
{
    assert(a);
    if (left >= right)
    {
        return;
    }
    else
    {
        int div = Partsort1(a, left, right);
        int div = Partsort2(a, left, right);
        int div = Partsort3(a, left, right);
        Quicksort(a, left, div - 1);
        Quicksort(a, div + 1, right);
    }
}
void Quicksort(int *a, int left, int right)
{
    stack<int> s;
    if (left < right)
    {
        s.push(right);
        s.push(right);
        while (s.empty())
        {
            int begin = s.top();
            s.pop();
            int end = s.top();
            s.pop();
            int div = part1(a, begin, end);
            int div = part2(a, begin, end);
            int div = part3(a, begin, end);
            if (begin < div - 1)
            {
                s.push(div - 1);
                s.push(begin);
            }
            if (div + 1 < end)
            {
                s.push(end);
                s.push(div + 1);
            }
        }
    }

}

6:归并排序
基本思想:归并排序有点类似于合并两个有序链表
归并排序是建立在归并操作上的一种有效的排序算法,该算法和快速排序都是采用分治法来设计算法的,区别在于归并排序把数组分为两个基本等长(最多相差一个元素)的子数组,分别排好序之后还要进行归并操作,而快速排序在拆分子数组的时候则有所不同,其取一个基准元素,拆分之后基准元素左边的元素都比基准元素小,右边的元素都不小于基准元素,这样只需要分别对两个子数组排序即可,不再像归并排序一样需要归并操作。归并排序是稳定的算法,其最坏的时间复杂度是O(n^2),其最好的时间复杂度是O(nlogn).
假设有数组 a,比较 a[i] 和 a[j] 的大小,若 a[i] ≤ a[j],则将第一个有序表中的元素 a[i] 复制到 r[k] 中,并令 i 和 k 分别加上 1;否则将第二个有序表中的元素 a[j] 复制到 r[k] 中,并令 j 和 k 分别加上 1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到 r 中从下标 k 到下标 t 的单元。归并排序的算法我们通常用递归实现,先把待排序区间 [s,t] 以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间 [s,t].

void _Merge(int *a, int* tmp, int begin1, int end1, int begin2, int end2)
{
    size_t index = begin1; size_t pos = begin2;
    while (begin1 < end1&&begin2 < end2)
    {
        if (a[begin1] < a[begin2])
        {
            tmp[index++] = a[begin1++];
        }
        else
        {
            tmp[pos++] = a[begin2++];
        }
    }
    if (begin1 >= end1)
    {
        while (begin2 < end2)
        {
            tmp[pos++] = a[begin2++];
        }

    }
    else if (begin2 >= end2)
    {
        while (begin1<end1)
        {
            tmp[index++] = a[begin1++];
        }
    }
    else
    {
        return;
    }
    memcpy(a + pos, tmp + pos, sizeof(int)*(end2 - pos + 1));
}
void _Mergesort(int*a, int *tmp, int left, int right)
{
    if (left >= right)
    {
        return;
    }
    else
    {
        int mid = left + (left + right) / 2;
        _Mergesort(a, tmp, left, mid);
        _Mergesort(a, tmp, mid + 1, right);
        _Merge(a, tmp, left, mid, mid + 1, right);
    }
}
void Mergesort(int *a, size_t n)
{
    assert(a);
    int *tmp = new int[n];
    _Mergesort(a, tmp, 0, n - 1);
}

7:冒泡排序
基本思想:即对相邻两个数进行比较,如果反序就交换位置,直到整个序列没有出现反序为止。
代码里面的flag是优化部分,如果第一趟没有发现有交换产生,则直接跳出循环,

void Bubble_sort(int *a, size_t n)
{
    int i, j, temp;
    bool flag = true;
    for (i = n - 1; i >= 0; i--)
    {
        flag = false;
        for (j = 0; j < i; j++)
        {
            if (a[j] >a[j + 1])
            {
                temp = a[j + 1];
                a[j + 1] = a[j];
                a[j] = temp;
                flag = true;
            }
            if (flag == false) break;
        }
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值