zoukankan      html  css  js  c++  java
  • [C++]各种排序算法合集(冒泡,选择,插入,shell,基数,快排,归并)

    #pragma once
    #ifndef SORT_COLLECTIONS_H_
    #define SORT_COLLECTIONS_H_
    #include <assert.h>
    #include <algorithm>
    #include <stdlib.h>
    #include <time.h>
    //#include "generic.h"
    using namespace std;
    namespace alg {
        //1:冒泡排序,时间复杂度为O(n^2),稳定,一种传统的排序方法,核心思想是通过不断的遍历整个数组交换顺序达到排序目的。
        template<typename T>
        static void BubbleSort(T list[], int start, int end) {
            int i;
            bool swapped;
            assert(start < end);
            do {
                swapped = false;
                for (int i = start + 1; i <= end; ++i) {
                    if (list[i - 1] > list[i]) {
                        swap(list[i - 1], list[i]);
                        swapped = true;
                    }
                }
                end--;
            } while (swapped);
        }
        //选择排序,时间复杂度为O(n^2),不稳定,从前到后,第一层循环所在的索引与其后面的值进行比较选择出最小的并进行交换,优点是不占用额外内存
        template <typename T>
        static void SelectionSort(T list[], int start, int end) {
            int i, j;
            int iMin;
            assert(start < end);
            for (j = start; j < end; ++j) {
                iMin = j;
                for (i = j + 1; i <= end; ++i) {
                    if (list[i] < list[iMin]) {
                        iMin = i;
                    }
                }
                if (j != iMin)
                    swap(list[j], list[iMin]);
            }
        }
        //插入排序,时间复杂度为O(n^2),稳定,第一层循环遍历后的所有元素都是已序的,第一层循环遍历到的每一个元素都会与前面已序元素进行比较,直到比已序的某个元素大时停止比较并插入其前面
        template<typename T>
        static void InsertionSort(T list[], int num_of_elems) {
            int i, j;
            for (i = 1; i < num_of_elems; ++i) {
                T current_elem = list[i];
                j = i - 1;
                while (j>=0&&list[j]>current_elem)
                {
                    list[j + 1] = list[j];
                    j--;
                }
                list[j + 1] = current_elem;
            }
        }
        //希尔排序,也叫递减增量排序算法,时间复杂度O(n^(1.3—2)),不稳定,选取合适的递减增量值,对不同增量下的子数组进行插入排序。
        template<typename T>
        static void ShellSort(T list[], int len) {
            int h = 1;
            int i, j;
            while (h < len / 3)
            {
                h = h * 3 + 1;
            }
            while (h>=1)
            {
                for (i = h; i < len; ++i) {
                    T current_elem = list[i];
                    j = i - h;
                    while (j >= 0&&current_elem<list[j])
                    {
                        list[j + h] = list[j];
                        j = j - h;
                    }
                    list[j + h] = current_elem;
                }
                h /= 3;
            }
        }
        //基数排序,时间复杂度O(d(n+rd)),稳定,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
        //for radix_sort,find the biggest number of list
        template <typename T>
        static int maxbit(T list[], int n) {
            int maxData = list[0];
            for (int i = 1; i < n; ++i) {
                if (maxData < list[i])
                    maxData = list[i];
            }
            int d = 1;
            int p = 10;
            while (maxData >= p)
            {
                maxData /= 10;
                d++;
            }
            return d;
        }
        template <typename T>
        static void RadixSort(T list[], int n) {
            int d = maxbit(list, n);
            int *temp = new T[n];
            int *count = new int[10];
            int i, j, k;
            int radix = 1;
            for (i = 0; i < d; ++i) {
                for (j = 0; j < 10; ++j)
                    count[j] = 0;
                for (j = 0; j < n; ++j) {
                    k = (list[j] / radix) % 10;
                    count[k]++;
                }
                for (j = 1; j < 10; ++j)
                    count[j] += count[j - 1];
                for (j = n - 1; j >= 0; --j) {
                    k = (list[j] / radix) % 10;
                    temp[count[k] - 1] = list[j];
                    count[k]--;
                }
                for (j = 0; j < n; ++j)
                    list[j] = temp[j];
                radix *= 10;
            }
            delete[] temp;
            delete[] count;
        }
        //快速排序,时间复杂度O(nlogn),不稳定,主要思想是选择基准哨兵,将原数组分为两部分进行,一边是都不大于基准的部分,一边是都大于基准的部分,按此法递归,直至整个数组有序。
        template<typename T>
        static int partition(T list[], int begin, int end) {
            srand(time(0));
            //int pivot_indx = RANDOM(begin, end);
            int pivot_indx = begin + rand() % (end - begin + 1);
            T pivot = list[pivot_indx];
            swap(list[begin], list[pivot_indx]);
            int i = begin + 1;
            int j = end;
            while (i <= j)
            {
                while (i <= end && (list[i] <= pivot))
                    ++i;
                while (j >= begin && (list[j] > pivot))
                    --j;
                if (i < j)
                    swap(list[i], list[j]);
            }
            swap(list[begin], list[j]);
            return j;
        }
        template<typename T>
        static void QuickSort(T list[], int begin, int end) {
            if (begin < end) {
                int pivot_indx=partition<T>(list, begin, end);
                QuickSort(list, begin, pivot_indx - 1);
                QuickSort(list, pivot_indx + 1, end);
            }
        }
        //归并排序,时间复杂度O(nlogn),稳定,将数组不断切分至单个元素,然后进行排序,将排序后的子数组再作为已序数组供上层进行选择排序。
        template<typename T>
        static void merge_(T *list, int l, int m, int h) {
            T *A = list + l;
            int lb = m - l;
            T *B = new T[lb+1];
            for (int i = 0; i <= lb; B[i] = A[i++]);
            int lc = h - (m + 1);
            T *C = list + m + 1;
            for (int i = 0, j = 0, k = 0; (j <= lb) || (k <= lc);) {
                if ((j <= lb) && (!(k <= lc) || (B[j] <= C[k])))
                    A[i++] = B[j++];
                if ((k <= lc) && (!(j <= lb) || (C[k] < B[j])))
                    A[i++] = C[k++];
    
            }
            delete[] B;
        }
        template<typename T>
        static void MergeSort(T *list, int l, int h) {
            if (h - l < 1) return;
            int m = (l + h) >> 1;
            MergeSort(list, l, m);
            MergeSort(list, m+1, h);
            merge_(list,l, m, h);
        }
    }
    #endif // !SORT_COLLECTIONS_H_

     排序算法的动图演示

    冒泡排序

    选择排序

    插入排序

    希尔排序

    基数排序

    归并排序

    图片转自--https://www.runoob.com/w3cnote_genre/algorithm

  • 相关阅读:
    由群里在职的同学给出污染物推断题想到的
    参考文献期刊和会议的缩写
    并行程序开发笔记
    对有关推理方法的理解---支离破碎篇
    改基金的困惑与无奈
    对生物信息学基础的补习
    DPI深度报文检测架构及关键技术实现
    OSGi 和 C++
    CentOS安装glibc-2.14,错误安装libc.so.6丢失急救办法
    误删除libc.so.6的解决方法
  • 原文地址:https://www.cnblogs.com/lightmonster/p/11237923.html
Copyright © 2011-2022 走看看