排序算法

排序算法


在计算机程序中,排序算法是很多其他算法的基础,可以为我们更好地完成其他工作,提升效率。


常见的排序算法有

  • 冒泡排序
  • 选择排序
  • 插入排序
  • 希尔排序
  • 快速排序
  • 归并排序
  • 堆排序

1、冒泡排序

冒泡排序的原理就是通过一次次把最小或者最大的元素推到未排序序列的一端,直到有序

template <class T>
void bubbleSort(T* arr, int size) {
    for (int i = 0; i < size - 1; i++) {
        bool change = false;
        for (int j = 0; j < size - 1 - i; j++) {
            if (_less(arr[j + 1], arr[j])) {
                _swap(arr[j], arr[j + 1]);
                change = true;
            }
        }
        if (!change)
            break;
    }
}

其中_swap和_less的定义如下,之后也会一直使用这两个函数

template <class T>
inline bool _less(const T& a, const T& b) {
    return a < b;
}

template <class T>
inline void _swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

2、选择排序

选择排序每次找到最小(大)的值,放到已排序片段的末端

template <class T>
void selectionSort(T* arr, int size) {
    for (int i = 0; i < size; i++) {
        int minIndex = i;
        for (int j = i + 1; j < size; j++) {
            if (_less(arr[j], arr[minIndex])) {
                minIndex = j;
            }
        }
        if (minIndex != i) {
            _swap(arr[minIndex], arr[i]);
        }
    }
}

3、插入排序

插入排序就类似整理扑克牌,过程上是这样的:

  1. 假定之前元素的已经排好序
  2. 取下一个元素的值,往前面插入到正确的位置,在其后面的元素需要整体向后挪一位
  3. 重复步骤1 2
template <class T>
void insertionSort(T*arr, int size) {
    for (int i = 1; i < size; i++) {
        T temp = arr[i];
        int j = i - 1;
        for (; j >= 0; j--) {
            if (_less(temp, arr[j]))
                arr[j + 1] = arr[j];
            else break;
        }
        arr[j + 1] = temp;
    }
}

4、希尔排序

希尔排序是插入排序的一个改进,插入排序的步长是1,而希尔排序的步长是由一个递减序列给定的,当步长是1的时候,每次移动一位,每次减少 1 个倒置数,所以倒置数是多少,就要移动多少次,而当步长从一个较大的值n开始,一次移动n个位置,倒置数就能一次减少n,这样极大的削减了倒置数,并且使数组局部有序,之后减少步长直到1,就相当于使用插入排序,此时插入排序效率很高。

template < class T>
void shellSort(T * arr, int size) {
    int  h = 1;
    while (3 * h + 1 < size)
        h = 3 * h + 1;
    while (h) {
        for (int i = h; i < size; i++) {
            T temp = arr[i];
            int j = i - h;
            for (; j >= 0; j -= h) {
                if (_less(temp, arr[j]))
                    arr[j + h] = arr[j];
                else break;
            }
            arr[j + h] = temp;
        }
        h /= 3;
    }
}

5、快速排序

快速排序的做法十分有创造力,在一个无序序列中取一个主元,把小于主元的部分放到左边,把大于主元的部分放到右边,再让左边和右边的序列递归重复这个过程,直到子序列长度<=1(不需要排序)。

template <class T>
void quickSort(T * arr, const int lo, const int hi) {
    if (hi <= lo)
        return;
    int lt = lo + 1, gt = hi;
    while (1) {
        while (lt <= hi && _less(arr[lt], arr[lo]))
            lt++;
        while (gt > lo && !_less(arr[gt], arr[lo]))
            gt--;
        if (lt < gt)
            _swap(arr[lt], arr[gt]);
        else
        {
            _swap(arr[lo], arr[gt]);
            break;
        }
    }
    quickSort(arr, lo, gt - 1);
    quickSort(arr, lt, hi);
}

6、 归并排序

归并排序的原理是
1. 把无序序列切分成小块,直到长度为1
2. 假定归并的序列都是有序的(上面的1,就是有序)
3. 逐渐扩大范围进行归并

template <class T>
void merge(T* arr, int lo, int mid, int hi, T* arr2) {
    if (mid > hi)
        mid = hi;
    int i = lo, j = mid + 1;
    for (int k = lo; k <= hi; k++)
        if (i > mid)
            arr2[k] = arr[j++];
        else if (j > hi)
            arr2[k] = arr[i++];
        else if (_less(arr[i], arr[j]))
            arr2[k] = arr[i++];
        else
            arr2[k] = arr[j++];
}

template <class T>
void mergeSort(T * arr, int lo, int hi) {
    T* originArr = arr;
    T * arr2 = new T[hi + 1];

    for (int step = 1; lo + step <= hi; step += step) {
        for (int i = lo; i <= hi; i += step + step) {
            merge(arr, i, i + step - 1, _min(i + step + step - 1, hi), arr2);
        }
        _swap(arr, arr2);
    }

    if (arr == originArr) {
        delete[]arr2;
        return;
    }
    else {
        for (int i = lo; i <= hi; i++) {
            arr2[i] = arr[i];
        }
        delete[]arr;
    }
}

上面的 merge 函数将 arr 看成两个有序部分,以 mid 分开,并将合并的结果放在 arr2中。
mergeSort 函数中将函数按步长切分,调用merge,每次循环交换arrarr2的值(数组地址)。最后还原到原始数组中。

7、堆排序

堆排序利用了完全二叉树的概念。
完全二叉树按照从左到右,从上到下的顺序将二叉树排满。
其原理如下:

  1. 首先将数组想象成一个完全二叉树,一般数组元素要从下标 1 开始存储,下标为 n 的元素的子节点分别是下标为 2n2n+1
  2. 对整个数组使用自上而下使用上浮函数,或者自下而上使用下沉函数。
  3. 交换下标 1 和 下标 size 的元素,size–,对下标 1 的元素使用下沉函数
  4. 重复步骤 3 直到 size==1
template <class T>
inline void swim(T *arr, int i) {
    int j = i / 2;
    while (j && _less(arr[i], arr[j])) {
        _swap(arr[i], arr[j]);
        i = j;
        j /= 2;
    }
}

template <class T>
void sink(T* arr, int i, int size) {
    while (2 * i <= size) {
        int j = 2 * i;
        if (j < size && _less(arr[j + 1], arr[j]))
            j++;
        if (_less(arr[j], arr[i]))
            _swap(arr[j], arr[i]);
        i = j;
    }
}

template <class T>
void heapSort(T* arr, int size) {
    size--;
    for (int i = 2; i <= size; i++) {
        swim(arr, i);
    }
    for (int i = size; i > 1; ) {
        _swap(arr[1], arr[i]);
        sink(arr, 1, --i);
    }

    for (int i = 0; i < size; i++) {
        if (_less(arr[i], arr[i + 1])) {
            _swap(arr[i], arr[i + 1]);
        }
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕业设计,基于SpringBoot+Vue+MySQL开发的影城管理系统,源码+数据库+论文答辩+毕业论文+视频演示 随着现在网络的快速发展,网上管理系统也逐渐快速发展起来,网上管理模式很快融入到了许多生活之,随之就产生了“小徐影城管理系统”,这样就让小徐影城管理系统更加方便简单。 对于本小徐影城管理系统的设计来说,系统开发主要是采用java语言技术,在整个系统的设计应用MySQL数据库来完成数据存储,具体根据小徐影城管理系统的现状来进行开发的,具体根据现实的需求来实现小徐影城管理系统网络化的管理,各类信息有序地进行存储,进入小徐影城管理系统页面之后,方可开始操作主控界面,主要功能包括管理员:首页、个人心、用户管理、电影类型管理、放映厅管理、电影信息管理、购票统计管理、系统管理、订单管理,用户前台;首页、电影信息、电影资讯、个人心、后台管理、在线客服等功能。 本论文主要讲述了小徐影城管理系统开发背景,该系统它主要是对需求分析和功能需求做了介绍,并且对系统做了详细的测试和总结。具体从业务流程、数据库设计和系统结构等多方面的问题。望能利用先进的计算机技术和网络技术来改变目前的小徐影城管理系统状况,提高管理效率。 关键词:小徐影城管理系统;Spring Boot框架,MySQL数据库
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值