算法学习(7) - 排序算法大集合

该篇博文长期更新,如有错误或者建议请评论留言,方便相互交流学习,谢谢。

1. 基本概念

1.1 稳定性

  • 稳定算法:
    排序序列中假设有几个比较关键词相等的元素,那么排序后这几个元素的前后相对位置不发生变化。
  • 不稳定算法:
    不能保证上述过程的算法称为不稳定算法。

算法的稳定性对于有些应用中比较重要。

1.2 时间性能

排序是数据处理中经常执行的一种操作,时间开销是衡量排序算法的一个重要标志。通常,在排序过程中需要进行下列两种操作:

  • 比较两个关键字的大小
  • 将元素从一个位置移动到另一位置

1.3 空间性能

空间性能是指排序过程中所需要的辅助存储空间的大小。辅助存储空间是除了存放待排序的数据所占用的存储空间之外,执行算法所需要的其他的存储空间。

2. 排序算法总结


排序算法

这里写图片描述

2. 插入排序

插入排序的基本思想:
从初始的子集合开始,不断地把新的数据元素插入到有序子集合中的合适位置,使有序子集合中数据元素的个数不断增加,直到有序子集合的大小等于带排序的数据元素集合的大小为止。
扑克牌的抓牌过程就是一个典型的插入排序。


插入排序

2.1 直接插入排序

顺序地把待排序的数据元素按其关键字值的大小插入到已排序子集合的适当位置,子集合的数据元素的个数逐渐增加,直至有序子集合的大小等于待排序数据元素集合的大小为止。
直接插入排序思想

  • 把顺序表A的第一个元素A[0]作为已序集合,将A[1]元素插入到已序集合中,以此类推可以将整个序列排序完成。

    插入排序动画演示
void InsertSort(int a[], int n)
{
        int i, j;
        int tmp = a[0];                                 //已序序列
        for(i=1; i<n; i++)
        {
                tmp = a[i];                             //带插入元素
                j = i-1;                                //待插入元素的前一个位置
                while(j>-1 && tmp<a[j])                 //当前元素查找合适插入位置
                {
                        a[j+1] = a[j];                  //向后移动已序序列
                        --j;    
                }
                a[j + 1] = tmp;                         //插入待插入元素

        }
}

2.2 希尔排序

/*
a[] 待排序序列 n待排序元素个数
d[] 增量序列 num增量序列长度
*/
void ShellSort(int a[], int n, int d[], int num)
{
        int i, j, k, m, span;
        int tmp;

        for(m = 0; m < num; ++m)                    
        {   
                span = d[m];
                for(k = 0; k < span; ++k)
                {   
                        for(i = k + span; i < n; i += span)
                        {   
                                tmp = a[i];
                                j = i - span;
                                while(j > -1 && tmp < a[j])
                                {   
                                        a[j + span] = a[j];
                                        j -= span;
                                }   
                                a[j + span] = tmp;
                        }   
                }   
        }   
}

3. 选择排序

3.1 直接选择排序

void SelectSort(int a[], int n)
{
        int i,j;
        for(i=0; i<n; ++i)
        {
                for(j = i+1; j<n; ++j)
                {
                        if(a[i] > a[j])
                                swap(&a[i], &a[j]);
                }
        }
}

3.2 堆排序


堆排序动画演示

void AdjustHeap(int a[], int n, int k)
{
        int i, j, flag;
        int tmp;
        i = k;
        j = 2*i + 1;
        tmp = a[i];
        flag = 0;

        while(j < n && flag != 1)
        {   
                if(j < n-1 && a[j] < a[j+1])
                        ++j;
                if(tmp >= a[j])
                {   
                        flag = 1;
                }   
                else
                {   
                        a[i] = a[j];
                        i = j;
                        j = 2*i + 1;
                }   
        }   
        a[i] = tmp;
}

void CreatInitHeap(int a[], int n)
{
        for(int i = (n-2)/2; i>=0; --i)
                AdjustHeap(a,n,i);
}

void HeapSort(int a[], int n)
{
        int i;
        int tmp;
        CreatInitHeap(a, n); 
        for(i = n-1; i > 0; --i)
        {
                tmp = a[0];
                a[0] = a[i];
                a[i] = tmp;
                AdjustHeap(a, i, 0);
        }
}

4. 交换排序

4.1 冒泡排序

void BubbleSort1(int a[], int n)
{
    int i,j;
    for(i = 0; i < n; ++i)
    {
        for(j = 1; j < n - i; ++j)
        {
            if(a[j-1] > a[j])
            {
                swap(&a[j-1], &a[j]);
            }
        }
    }
}

void BubbleSort2(int a[], int n)
{
    int i, j;
    char flag = 0;

    while(flag == 0)
    {
        flag = 1;
        for(j = 1; j < n - i; ++j)
        {
            if(a[j-1] > a[j])
            {
                swap(&a[j-1], &a[j]);
                flag = 0;
            }
        }
        ++i;
    }
}

void BubbleSort3(int a[], int n)
{
    int i, j;
    int flag = n;

    while(flag > 0)
    {
        i = flag;
        flag = 0;
        for(j = 1; j < i; ++j)
        {
            if(a[j-1] > a[j])
            {
                swap(&a[j-1], &a[j]);
                flag = j;
            }
        }
    }
}

4.2 快速排序

#include <iostream>
#include <stack>
using namespace std;

/*
对数组进行一次划分,arr[l]作为枢纽元素
l, r均为数据元素下标
*/
int partition(int *arr, int l, int r)
{
    int i = l, j = r;                                   
    int key = arr[l];                                   //枢纽元素
    while (i < j)
    {
        while (i < j && arr[j] >= key) j--;             //从右往左找到一个比枢纽小的
        if (i < j)
        {
            arr[i] = arr[j];
            i++;
        }
        while (i < j && arr[i] < key) i++;              //从右往左找到一个比枢纽大的
        if (i < j)
        {
            arr[j] = arr[i];
            j--;
        }
    }
    arr[i] = key;
    return i;
}

/*
对数组进行一次划分,arr[l]作为枢纽元素
l, r均为数据元素下标
*/
void QuickSort(int *arr, int l, int r)
{
    if (l < r)
    {
        int par = partition(arr, l, r);
        QuickSort(arr, l, par - 1);
        QuickSort(arr, par + 1, r);
    }
}

void QuickSort2(int *arr, int l, int r)
{
    stack<int> tmp;                             //临时栈
    if (l < r)                                  //
    {
        int par = partition(arr, l, r);         //

        if (l < par - 1)                        //
        {
            tmp.push(l);                        //
            tmp.push(par-1);
        }
        if (par + 1 < r)
        {
            tmp.push(par + 1);
            tmp.push(r);
        }

        while (!tmp.empty())
        {
            r = tmp.top(); tmp.pop();
            l = tmp.top(); tmp.pop();

            par = partition(arr, l, r);

            if (l < par - 1)
            {
                tmp.push(l); tmp.push(par - 1);
            }

            if (par + 1 < r)
            {
                tmp.push(par + 1); tmp.push(r);
            }
        }
    }
}


int main()
{
    int arr[] = { 3, 1, 2, 6, 7, 8, 9, 4, 5 };
    int rt = partition(arr, 0, 8);
    QuickSort2(arr, 0, 8);

    cout << "rt = " << rt << endl;

    for (int i = 0; i < 9; ++i)
        cout << arr[i] << " ";

    cout << endl;
    return 0;
}
void QuickSort(int a[], const int low, const int high)
{
        int i,j;
        int tmp;
        i = low;
        j = high;
        tmp = a[low];
        while(i < j)
        {
                while(i<j && a[j]>=tmp) --j;

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

                while(i <j && a[i] < tmp) ++i;

                if(i < j)
                {
                        a[j] = a[i];
                        j--;
                }
        }
        a[i] = tmp;
        if(low < i-1)
                QuickSort(a, low, i-1);
        if(j + 1 < high)
                QuickSort(a, j+1, high);
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空空的司马

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值