目录

插入排序

Bubble-Sort

Shell-Sort

其它可以参考相关博客

八种经典内部排序算法

八种排序算法以及Java代码的实现

剖析八种经典排序算法

十个常用排序算法python3实现

C/C++八种排序算法原理及实现



插入排序

算法与数据结构 第2章 排序基础 下 插入排序_#endif

算法与数据结构 第2章 排序基础 下 插入排序_ios_02

算法与数据结构 第2章 排序基础 下 插入排序_#include_03

算法与数据结构 第2章 排序基础 下 插入排序_#endif_04

算法与数据结构 第2章 排序基础 下 插入排序_ios_05

算法与数据结构 第2章 排序基础 下 插入排序_数组_06

算法与数据结构 第2章 排序基础 下 插入排序_ios_07

算法与数据结构 第2章 排序基础 下 插入排序_#endif_08

---------------------

依次类推,当前元素与前面的元素一一对比

  template<typename T>
    void insertionSort1(T arr[], int n){

        for (int i = 0; i < n; ++i) {
            if(arr[i] < arr[i+1])
            {
                std::swap(arr[i], arr[i+1]);
                if (i>=2)
                {
                   for(int j = i-1; j > 0, i > 0; --j,--i)
                   {
                       if (arr[j] < arr[i])
                       {
                           std::swap(arr[j], arr[i]);
                       }
                   }
                }
            }
        }
    }


    template<typename T>
    void insertionSort2(T arr[], int n){
        for (int i = 1; i < n; ++i) {
            for (int j = i; j > 0 ; --j) {
                if (arr[j] > arr[j-1])
                    std::swap(arr[j], arr[j-1]);
            }
        }
    }

    template<typename T>
    void insertionSort3(T arr[], int n){
        for (int i = 1; i < n; ++i) {
            for (int j = i; j > 0 && (arr[j] > arr[j-1]); --j)
                //可以提前结束程序通过比较,如果数据有一定的顺序则会更快
            {
                std::swap(arr[j], arr[j-1]);
//                swap操作需要三次赋值,会降低效率
            }
        }
    }
swap操作需要三次赋值,会降低效率,可以改进

算法与数据结构 第2章 排序基础 下 插入排序_ios_09

算法与数据结构 第2章 排序基础 下 插入排序_#endif_10

算法与数据结构 第2章 排序基础 下 插入排序_#include_11

将当前元素复制一份,看其是否放在当前的位置,通过与其前面一个元素对比

算法与数据结构 第2章 排序基础 下 插入排序_#endif_12

算法与数据结构 第2章 排序基础 下 插入排序_ios_13

算法与数据结构 第2章 排序基础 下 插入排序_#endif_14

算法与数据结构 第2章 排序基础 下 插入排序_#endif_15

把交换变成了比较之后的一次赋值

 

    template<typename T>
    void insertionSort4(T arr[], int n){
        for (int i = 1; i < n; ++i) {
            T temp = arr[i];
            int j = 0; //保存元素temp应该放的位置

            for ( j = i; j > 0 && (arr[j-1] < temp); --j)
            {
                arr[j] = arr[j-1];
            }
            arr[j] = temp;
        }
    }
SortTestHelper.h
//
// Created by 天人合一 on 2020/6/16.
//

#ifndef CLIONBUFFER_SORTTESTHELPER_H
#define CLIONBUFFER_SORTTESTHELPER_H

#include <iostream>
#include <ctime>
#include <cassert>
#include <string>

namespace SortTestHelper{

    template<typename T>
    void insertionSort1(T arr[], int n){

        for (int i = 0; i < n; ++i) {
            if(arr[i] < arr[i+1])
            {
                std::swap(arr[i], arr[i+1]);
                if (i>=2)
                {
                   for(int j = i-1; j > 0, i > 0; --j,--i)
                   {
                       if (arr[j] < arr[i])
                       {
                           std::swap(arr[j], arr[i]);
                       }
                   }
                }
            }
        }
    }


    template<typename T>
    void insertionSort2(T arr[], int n){
        for (int i = 1; i < n; ++i) {
            for (int j = i; j > 0 ; --j) {
                if (arr[j] > arr[j-1])
                    std::swap(arr[j], arr[j-1]);
            }
        }
    }

    template<typename T>
    void insertionSort3(T arr[], int n){
        for (int i = 1; i < n; ++i) {
            for (int j = i; j > 0 && (arr[j] > arr[j-1]); --j)
                //可以提前结束程序通过比较,如果数据有一定的顺序则会更快
            {
                std::swap(arr[j], arr[j-1]);
//                swap操作需要三次赋值,会降低效率
            }
        }
    }

    template<typename T>
    void insertionSort4(T arr[], int n){
        for (int i = 1; i < n; ++i) {
            T temp = arr[i];
            int j = 0;

            for ( j = i; j > 0 && (arr[j-1] < temp); --j)
            {
                arr[j] = arr[j-1];
            }
            arr[j] = temp;
        }
    }


    template<typename T>
    bool isSort(T arr[], int n)
    {
        for (int i = 0; i < n; ++i) {
           assert(arr[i] >= arr[i+1]);
            return true;
        }
    }

    template<typename T>
    bool isSorted(T arr[], int n)
    {
        for (int i = 0; i < n - 1; ++i) {
            if (arr[i] < arr[i+1])
                return false;
        return true;
        }
    }

//    返回的创建的数组
// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR]
    int* generateRandomArray(int n, int rangeL, int rangeR){
        assert( rangeL <= rangeR);
        int* arr = new int[n];
        srand(time(NULL));
        for (int i = 0; i < n; ++i) {
//            rand()%(rangeR-rangeL+1)表示0到rangeR-rangeL区间的随机数
            arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
        }
        return arr;
    }

//    生成一个近乎有顺的数组
    int *generateNearlyOrderedArray(int n, int swapTimes){
//    先生成一个有顺的数组
        int *arr = new int[n];
//        for(int i = 0 ; i < n ; i ++ )
            for(int i = n-1 ; i >= 0 ; i -- )
                arr[i] = n - i;
//再随机的根据自己的需要交换一些数据的顺序
        srand(time(NULL));
        for( int i = 0 ; i < swapTimes ; i ++ ){
            int posx = rand()%n;
            int posy = rand()%n;
            std::swap( arr[posx] , arr[posy] );
        }
        return arr;
    }


    template<typename T>
    void selectionSort4(T array[], int n)
    {
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                if(array[i] < array[j])
                {
                    swap( array[i], array[j]);
                }
            }
        }
    }

    template <typename T>
    void print_array(T array[], int n)
    {
        for (int i = 0; i < n; ++i)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    }

    template<typename T>
    void printArray(T arr[], int n) {

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

        return;
    }

    template<typename T>
    void testSort(const std::string &sortName, void (*sort)(T[], int), T arr[], int n ){

        clock_t startTime = clock();
        sort(arr, n);
        clock_t endTime = clock();

        assert(isSorted(arr, n));
        std::cout << sortName << " : " << double(endTime-startTime) / CLOCKS_PER_SEC << " s " << std::endl;
    }

//    数组的copy
     int* arrayCopy(int* T, int n)
    {
         int* arr = new int[n];
         std::copy(T, T + n, arr);
        return arr;
    }

}

#endif //CLIONBUFFER_SORTTESTHELPER_H

main.cpp

#include <iostream>
#include <algorithm>
#include "SortTestHelper.h"

using namespace std;

int main0() {

//   1 整形数组测试
    int num = 10;
    int* intarr = SortTestHelper::generateRandomArray(num, 2, 100);
//    printf("----------------int: sort before ----------------\n");
//    SortTestHelper::print_array(intarr, num);
//
//
//
    SortTestHelper::selectionSort4(intarr, num);
    SortTestHelper::insertionSort1(intarr,num);
//    SortTestHelper::insertionSort3(intarr,num);
//
//    printf("----------------int: sort after ----------------\n");
//    SortTestHelper::print_array(intarr, num);

//插入排序因为先进行两两元素的对比,再交换使得效率更高
    int n = 10000;
    int *arr = SortTestHelper::generateRandomArray(n,0,n);
    int *arrInsert = SortTestHelper::arrayCopy(arr, n);
    int *arrImproved = SortTestHelper::arrayCopy(arr, n);
    SortTestHelper::testSort("Selection Sort", SortTestHelper::selectionSort4, arr, n);
//    SortTestHelper::printArray(arr, n);

    SortTestHelper::testSort("insertion sort swap", SortTestHelper::insertionSort3, arrInsert, n);
    SortTestHelper::testSort("insertion sort improved", SortTestHelper::insertionSort4, arrImproved, n);


//    SortTestHelper::print_array(arr, n);

//    for (int i = 0; i < 50; ++i) {
//        num += i;
//        int* testArr = SortTestHelper::generateRandomArray(num, 2, 100);
//        SortTestHelper::insertionSort(testArr, num);
//
//        if (SortTestHelper::isSort(intarr, num))
//            cout << "-------------------Good--------------" << endl;
//    }



    delete [] intarr;
    delete [] arr;
    delete [] arrInsert;
    delete [] arrImproved;

    return 0;
}


int main() {

//插入排序因为先进行两两元素的对比,再交换使得效率更高
//要排序的数据接近有顺时插入排序效率会很高,两者区别明显
    int n = 100000;
    int *arr = SortTestHelper::generateNearlyOrderedArray(n,1);
//        SortTestHelper::printArray(arr, n);

    int *arrInsert = SortTestHelper::arrayCopy(arr, n);
    int *arrImproved = SortTestHelper::arrayCopy(arr, n);
    SortTestHelper::testSort("Selection Sort", SortTestHelper::selectionSort4, arr, n);
//    SortTestHelper::printArray(arr, n);

    SortTestHelper::testSort("insertion sort swap", SortTestHelper::insertionSort3, arrInsert, n);
//        SortTestHelper::printArray(arr, n);

    SortTestHelper::testSort("insertion sort improved", SortTestHelper::insertionSort4, arrImproved, n);
//        SortTestHelper::printArray(arr, n);


    delete [] arr;
    delete [] arrInsert;
    delete [] arrImproved;

    return 0;
}

算法与数据结构 第2章 排序基础 下 插入排序_排序算法_16

算法与数据结构 第2章 排序基础 下 插入排序_ios_17

算法与数据结构 第2章 排序基础 下 插入排序_#include_18

SortTestHelper.h

//
// Created by liuyubobobo on 7/13/16.
//

#ifndef INC_04_INSERTION_SORT_SORTTESTHELPER_H
#define INC_04_INSERTION_SORT_SORTTESTHELPER_H

#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
#include <cassert>

using namespace std;


namespace SortTestHelper {

    int *generateRandomArray(int n, int range_l, int range_r) {

        int *arr = new int[n];

        srand(time(NULL));
        for (int i = 0; i < n; i++)
            arr[i] = rand() % (range_r - range_l + 1) + range_l;
        return arr;
    }

    int *generateNearlyOrderedArray(int n, int swapTimes){

        int *arr = new int[n];
        for(int i = 0 ; i < n ; i ++ )
            arr[i] = i;

        srand(time(NULL));
        for( int i = 0 ; i < swapTimes ; i ++ ){
            int posx = rand()%n;
            int posy = rand()%n;
            swap( arr[posx] , arr[posy] );
        }

        return arr;
    }

    int *copyIntArray(int a[], int n){

        int *arr = new int[n];
        copy(a, a+n, arr);
        return arr;
    }

    template<typename T>
    void printArray(T arr[], int n) {

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

        return;
    }

    template<typename T>
    bool isSorted(T arr[], int n) {

        for (int i = 0; i < n - 1; i++)
            if (arr[i] > arr[i + 1])
                return false;

        return true;
    }

    template<typename T>
    void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {

        clock_t startTime = clock();
        sort(arr, n);
        clock_t endTime = clock();
        cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s"<<endl;

        assert(isSorted(arr, n));

        return;
    }

};

#endif //INC_04_INSERTION_SORT_SORTTESTHELPER_H
#include <iostream>
#include <algorithm>
#include "SortTestHelper.h"


using namespace std;


template<typename T>
void selectionSort(T arr[], int n){

    for(int i = 0 ; i < n ; i ++){

        int minIndex = i;
        for( int j = i + 1 ; j < n ; j ++ )
            if( arr[j] < arr[minIndex] )
                minIndex = j;

        swap( arr[i] , arr[minIndex] );
    }
}

template<typename T>
void insertionSort(T arr[], int n){

    for( int i = 1 ; i < n ; i ++ ) {

        // 寻找元素arr[i]合适的插入位置
        // 写法1
//        for( int j = i ; j > 0 ; j-- )
//            if( arr[j] < arr[j-1] )
//                swap( arr[j] , arr[j-1] );
//            else
//                break;

        // 写法2
        for( int j = i ; j > 0 && arr[j] < arr[j-1] ; j -- )
            swap( arr[j] , arr[j-1] );

    }

    return;
}

int main() {

    int n = 10000;
    cout<<"Test for Random Array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;
    int *arr1 = SortTestHelper::generateRandomArray(n,0,n);
    int *arr2 = SortTestHelper::copyIntArray(arr1, n);

    SortTestHelper::testSort("Insertion Sort", insertionSort,arr1,n);
    SortTestHelper::testSort("Selection Sort", selectionSort,arr2,n);

    delete[] arr1;
    delete[] arr2;

    cout<<endl;

    return 0;
}

进一步思想

//A:输入数组,len:数组长度
void insertSort(int A[],int len)
{
    int temp;
    for(int i=1;i<len;i++)
    {
        int j=i-1;
        temp=A[i];
        //查找到要插入的位置
        while(j>=0&&A[j]>temp)
        {
            A[j+1]=A[j];
            j--;
        }
//        if(j!=i-1)
            A[j+1]=temp;
    }
}

//A:输入数组,len:数组长度
void insertSort1(int A[],int len)
{
    int temp;
    for(int i=1;i<len;i++)
    {
        int j=i;
        temp=A[i];
        //查找到要插入的位置
        while( j>=1 && A[j-1] > temp )
        {
            A[j] = A[j-1];
            j--;
        }
        A[j] = temp;
    }
}

int main(){

    int num = 100;
    int* intarr = SortTestHelper::generateRandomArray(num, 2, 100);
    insertSort1(intarr,num);
    bool door = SortTestHelper::isSorted(intarr,num);
    if(!door)
        cout << "惊起却回头,有恨无人省。" << endl;
    else
        cout << "从此小舟逝,江海寄余生!" << endl;

//    SortTestHelper::printArray(intarr, num);

    return 0;
}

 

 

Bubble-Sort

传智播客扫地僧C/C++学习笔记冒泡排序

算法与数据结构 第2章 排序基础 下 插入排序_ios_19

InsertionSort.h

//
// Created by liuyubobobo on 7/15/16.
//

#ifndef OPTIONAL_01_BUBBLE_SORT_INSERTIONSORT_H
#define OPTIONAL_01_BUBBLE_SORT_INSERTIONSORT_H

#include <iostream>
#include <algorithm>

using namespace std;


template<typename T>
void insertionSort(T arr[], int n){

    for( int i = 1 ; i < n ; i ++ ) {

        T e = arr[i];
        int j;
        for (j = i; j > 0 && arr[j-1] > e; j--)
            arr[j] = arr[j-1];
        arr[j] = e;
    }

    return;
}

#endif //OPTIONAL_01_BUBBLE_SORT_INSERTIONSORT_H

SelectionSort.h

//
// Created by liuyubobobo on 7/15/16.
//

#ifndef OPTIONAL_01_BUBBLE_SORT_SELECTIONSORT_H
#define OPTIONAL_01_BUBBLE_SORT_SELECTIONSORT_H

#include <iostream>
#include <algorithm>

using namespace std;


template<typename T>
void selectionSort(T arr[], int n){

    for(int i = 0 ; i < n ; i ++){

        int minIndex = i;
        for( int j = i + 1 ; j < n ; j ++ )
            if( arr[j] < arr[minIndex] )
                minIndex = j;

        swap( arr[i] , arr[minIndex] );
    }
}

#endif //OPTIONAL_01_BUBBLE_SORT_SELECTIONSORT_H

main.cpp

#include <iostream>
#include <algorithm>
#include "SortTestHelper.h"
#include "SelectionSort.h"
#include "InsertionSort.h"

using namespace std;


template<typename T>
void bubbleSort( T arr[] , int n){

    bool swapped;
    //int newn; // 理论上,可以使用newn进行优化,但实际优化效果较差

    do{
        swapped = false;
        //newn = 0;
        for( int i = 1 ; i < n ; i ++ )
            if( arr[i-1] > arr[i] ){
                swap( arr[i-1] , arr[i] );
                swapped = true;

                // 可以记录最后一次的交换位置,在此之后的元素在下一轮扫描中均不考虑
                // 实际优化效果较差,因为引入了newn这个新的变量
                //newn = n;
            }

        //n = newn;

        // 优化,每一趟Bubble Sort都将最大的元素放在了最后的位置
        // 所以下一次排序,最后的元素可以不再考虑
        // 理论上,newn的优化是这个优化的复杂版本,应该更有效
        // 实测,使用这种简单优化,时间性能更好
        n --;

    }while(swapped);
}

int main() {

    int n = 10000;

    // Test for Random Array
    cout<<"Test for Random Array, size = "<<n<<", randome range [0, "<<n<<"]"<<endl;

    int *arr1 = SortTestHelper::generateRandomArray(n,0,n);
    int *arr2 = SortTestHelper::copyIntArray(arr1, n);
    int *arr3 = SortTestHelper::copyIntArray(arr1, n);

    SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n);
    SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
    SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n);

    delete[] arr1;
    delete[] arr2;
    delete[] arr3;

    cout<<endl;


    // Test for Random Nearly Ordered Array
    int swapTimes = 100;

    cout<<"Test for Random Nearly Ordered Array, size = "<<n<<", swap time = "<<swapTimes<<endl;

    arr1 = SortTestHelper::generateNearlyOrderedArray(n, swapTimes);
    arr2 = SortTestHelper::copyIntArray(arr1, n);
    arr3 = SortTestHelper::copyIntArray(arr1, n);

    SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n);
    SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
    SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n);

    delete[] arr1;
    delete[] arr2;
    delete[] arr3;

    return 0;
}

 

Shell-Sort

算法与数据结构 第2章 排序基础 下 插入排序_数组_20

BubbleSort.h

//
// Created by liuyubobobo on 7/15/16.
//

#ifndef OPTIONAL_02_SHELL_SORT_BUBBLESORT_H
#define OPTIONAL_02_SHELL_SORT_BUBBLESORT_H

#include <iostream>
#include <algorithm>

using namespace std;


template<typename T>
void bubbleSort( T arr[] , int n){

    bool swapped;

    do{
        swapped = false;
        for( int i = 1 ; i < n ; i ++ )
            if( arr[i-1] > arr[i] ){
                swap( arr[i-1] , arr[i] );
                swapped = true;
            }

        n --;

    }while(swapped);
}

#endif //OPTIONAL_02_SHELL_SORT_BUBBLESORT_H

InsertionSort.h

//
// Created by liuyubobobo on 7/15/16.
//

#ifndef OPTIONAL_02_SHELL_SORT_INSERTIONSORT_H
#define OPTIONAL_02_SHELL_SORT_INSERTIONSORT_H

#include <iostream>
#include <algorithm>

using namespace std;


template<typename T>
void insertionSort(T arr[], int n){

    for( int i = 1 ; i < n ; i ++ ) {

        T e = arr[i];
        int j;
        for (j = i; j > 0 && arr[j-1] > e; j--)
            arr[j] = arr[j-1];
        arr[j] = e;
    }

    return;
}

#endif //OPTIONAL_02_SHELL_SORT_INSERTIONSORT_H

SelectionSort.h

//
// Created by liuyubobobo on 7/15/16.
//

#ifndef OPTIONAL_02_SHELL_SORT_SELECTIONSORT_H
#define OPTIONAL_02_SHELL_SORT_SELECTIONSORT_H

#include <iostream>
#include <algorithm>

using namespace std;


template<typename T>
void selectionSort(T arr[], int n){

    for(int i = 0 ; i < n ; i ++){

        int minIndex = i;
        for( int j = i + 1 ; j < n ; j ++ )
            if( arr[j] < arr[minIndex] )
                minIndex = j;

        swap( arr[i] , arr[minIndex] );
    }
}

#endif //OPTIONAL_02_SHELL_SORT_SELECTIONSORT_H

main.cpp

#include <iostream>
#include "SortTestHelper.h"
#include "SelectionSort.h"
#include "InsertionSort.h"
#include "BubbleSort.h"

using namespace std;


template<typename T>
void shellSort(T arr[], int n){

    int h = 1;
    while( h < n/3 )
        h = 3 * h + 1;
    // 计算 increment sequence: 1, 4, 13, 40, 121, 364, 1093...

    while( h >= 1 ){

        // h-sort the array
        for( int i = h ; i < n ; i ++ ){

            // 对 arr[i], arr[i-h], arr[i-2*h], arr[i-3*h]... 使用插入排序
            T e = arr[i];
            int j;
            for( j = i ; j >= h && e < arr[j-h] ; j -= h )
                arr[j] = arr[j-h];
            arr[j] = e;
        }

        h /= 3;
    }
}


int main() {

    int n = 10000;

    // Test for Random Array
    cout<<"Test for Random Array, size = "<<n<<", random range [0, "<<n<<"]"<<endl;

    int *arr1 = SortTestHelper::generateRandomArray(n,0,n);
    int *arr2 = SortTestHelper::copyIntArray(arr1, n);
    int *arr3 = SortTestHelper::copyIntArray(arr1, n);
    int *arr4 = SortTestHelper::copyIntArray(arr1, n);

    SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n);
    SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
    SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n);
    SortTestHelper::testSort("Shell Sort", shellSort, arr4, n);

    delete[] arr1;
    delete[] arr2;
    delete[] arr3;
    delete[] arr4;

    cout<<endl;


    // Test for Random Nearly Ordered Array
    int swapTimes = 100;

    cout<<"Test for Random Nearly Ordered Array, size = "<<n<<", swap time = "<<swapTimes<<endl;

    arr1 = SortTestHelper::generateNearlyOrderedArray(n, swapTimes);
    arr2 = SortTestHelper::copyIntArray(arr1, n);
    arr3 = SortTestHelper::copyIntArray(arr1, n);
    arr4 = SortTestHelper::copyIntArray(arr1, n);

    SortTestHelper::testSort("Selection Sort", selectionSort, arr1, n);
    SortTestHelper::testSort("Insertion Sort", insertionSort, arr2, n);
    SortTestHelper::testSort("Bubble Sort", bubbleSort, arr3, n);
    SortTestHelper::testSort("Shell Sort", shellSort, arr4, n);

    delete[] arr1;
    delete[] arr2;
    delete[] arr3;
    delete[] arr4;

    return 0;
}
其它可以参考相关博客

八种经典内部排序算法

八种排序算法以及Java代码的实现

剖析八种经典排序算法

十个常用排序算法python3实现

C/C++八种排序算法原理及实现