各种排序算法实现

//  此版本为调整优化好的快速排序算法实现。
# include <iostream>
# include <vector>
using namespace std;
int Partition(vector<int> &arr, int low, int high)
{
    int pivot;                // 划分后基准记录的位置
    int pivotkey = arr[low]; // 用区间的第一个值作为基准,也可以采用其他方式,比如三数取中
    while (low < high)
    {
        while (low < high && arr[high] >= pivotkey) // 先从右向左扫描
            high--;
        if (low < high)      // 每次必须有判断,因为有可能在此时出现low>high的情况
            arr[low++] = arr[high];
        while (low < high && arr[low] <= pivotkey) // 再从左向右扫描
            low++;
        if(low < high)
            arr[high--] = arr[low];
    }
    pivot = low;           // 找出基准位置
    arr[pivot] = pivotkey; // 基准位置定位
    return pivot;
}
// 典型的分治法的思想
void quicksort(vector<int> &arr, int low, int high)
{
    if (low < high)  // 仅当区间长度大于 1 时才排序
    {
        int pivot = Partition(arr, low, high);  // 分解,找出基准
        quicksort(arr, low, pivot-1);           // 递归求解左子区间
        quicksort(arr, pivot + 1, high);        // 递归求解右子区间
    }
}
int main ()
{
    vector<int> arr;
    int temp;
    while (cin >> temp)
    {
        arr.push_back(temp); // 将数存入数组
    }
    quicksort(arr, 0, arr.size() - 1);
    for(auto i : arr)
        cout << i << endl;
    return 0;
}
// 优化的冒泡算法实现
# include <iostream>
# include <vector>
using namespace std;
void BubbleSort(vector<int> &arr)
{
    int i , j, temp,len;
    len =  arr.size();
    for (i = 0; i < len - 1; i++)  // 外层循环控制无序区的终点位置
    {
        bool flag = true;
        for (j = len - 1; j > i; j--) //内层控制每次比较的位置
        {
            if (arr[j] < arr[j - 1])
            {
                temp = arr[j];
                arr[j] = arr[j -1];
                arr[j - 1] = temp;
                flag = false;
            }
        }
        if (flag)
            break;
    }
}
int main()
{
    vector<int> arr;
    int temp;
    while (cin >> temp)
    {
        arr.push_back(temp); // 将数存入数组
    }
    BubbleSort(arr);
    cout <<"after sort: "<< endl;
    for(auto i : arr)
        cout << i << endl;
    return 0;
}
// 简单选择算法实现,相比于冒泡排序,最大的特点是数据交换移动次数较少,找到合适的关键字(最小值的位置)再交换
# include <iostream>
# include <vector>
using namespace std;
void SelectSort(vector<int> &arr)
{
    int i , j, temp,len, minindex;
    len =  arr.size();
    for (i = 0; i < len - 1; i++)  // 外层循环控制无序区的起点位置
    {
        minindex = i;
        for (j = i + 1; j <= len ; j++) //内层控制每次比较的位置,注意范围控制
        {
            if (arr[j] < arr[minindex])
                minindex = j;
        }
        if (minindex != i)  // 若有比当前值还小的最小值,则将最小值放到无序区的起点位置
        {
            temp = arr[minindex];
            arr[minindex] = arr[i];
            arr[i] = temp;
        }
    }
}
int main()
{
    vector<int> arr;
    int temp;
    while (cin >> temp)
    {
        arr.push_back(temp); // 将数存入数组
    }
    SelectSort(arr);
    cout <<"after sort: "<< endl;
    for(auto i : arr)
        cout << i << endl;
    return 0;
}
// 直接插入排序算法实现: 基本操作是讲一个记录插入到已经排好序的有序表汇总,
// 从而得到 一个新的、记录数增1的有序表
// 时间复杂度: O(n^2)
// author: SimplePaul
# include <iostream>
# include <vector>
using namespace std;
void InsertSort(vector<int> &arr)
{
    int i , j, temp,len;
    len =  arr.size();
    for (i = 1; i <= len - 1; i++)  //
    {
        if(arr[i] < arr[i-1])   // 若当前比前一个小,则需要交换,否则不交换
        {
            temp = arr[i];    // 保存当前的值
            for ( j = i - 1; arr[j] > temp && j >= 0; j--) // j>= 0的条件容易忘
            {
                arr[j + 1] = arr[j];   // 记录后移,直到当前值比temp要小
            }
            arr[j + 1] = temp;
        }
    }
}
int main()
{
    vector<int> arr;
    int temp;
    while (cin >> temp)
    {
        arr.push_back(temp); // 将数存入数组
    }
    InsertSort(arr);
    cout <<"after sort: "<< endl;
    for(auto i : arr)
        cout << i << endl;
    return 0;
}
// 希尔排序算法实现: 希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进
// 该方法又称缩小增量排序,希尔排序实质上是一种分组插入方法。它的基本思想是:对于n个待排序的数列,
//取一个小于n的整数gap(gap被称为步长)将待排序元素分成若干个组子序列,所有距离为gap的倍数的记录
//放在同一个组中;然后,对各组内的元素进行直接插入排序。 这一趟排序完成之后,每一个组的元素都是
//有序的。然后减小gap的值,并重复执行上述的分组和排序。重复这样的操作,当gap=1时,整个数列就是有序的。

// 相当于是     插入排序只是执行了希尔排序的gap=1的情况
// 时间复杂度: O(nlog(n))~O(n^2)  ,不稳定排序
// author: SimplePaul

# include <iostream>
# include <vector>
using namespace std;
void ShellSort(vector<int> &arr)
{
    int i , j, temp,len,gap;
    len =  arr.size();
    gap = len / 2;       // 取增量
    while (gap >= 1)
    {

        for (i = gap; i <= len - 1; i += gap)  // 进行插入排序,相当于原来每次插入排序的间隔为1,现在为gap
        {
            if(arr[i] < arr[i - gap]) // 若当前比前一个(前一个指相差gap的前一个值)小,则需要交换,否则不交换
            {
                temp = arr[i];        // 保存当前的值
                for ( j = i - gap; arr[j] > temp && j >= 0; j -= gap) // j>= 0的条件容易忘
                {
                    arr[j + gap] = arr[j];   // 每次记录后移gap,直到当前值比temp要小
                }
                arr[j + gap] = temp;   
            }
        }
        gap /= 2;   // 设置新的增量
    }

}
int main()
{
    vector<int> arr;
    int temp;
    while (cin >> temp)
    {
        arr.push_back(temp); // 将数存入数组
    }
    ShellSort(arr);
    cout <<"after sort: "<< endl;
    for(auto i : arr)
        cout << i << endl;
    return 0;
}

 堆排序实现:参考源

// 堆排序实现:
// 复杂度: O(NlogN)
//
堆排序快速排序归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法
#include <iostream>
using namespace std;
// 最大堆的向下调整算法  MaxHeapDown()
// 数组实现的堆中,第N个结点的左孩子的索引值是(2N+1),右孩子的索引是(2N+2)
// 其中,N为数组下标索引值,如数组第一个数对应的N为0。
// 参数说明:
//          a: 待排序的数组
//          start: 被下调节点的起始位置(一般为0,表示从第一个开始)
//          ends: 截止范围(一般为数组中最后一个元素的索引)
void MaxHeapDown(int* a, int start, int ends)
{
    int c = start;  // 当前(current)节点的位置
    int l = 2 * c + 1; // 左(left)孩子的位置
    int tmp = a[c];    // 当前节点的大小
    for (; l <= ends; c = l, l = 2*l + 1)
    {
        // l 是左孩子, l + 1 是右孩子
        if ( l < ends && a[l] < a[l + 1])
            l++;  // 左右两个孩子中选择较大者
        if (tmp >= a[l])
            break;   // 若当前节点的值比两个孩子中的大者还大 就结束循环
        //若是需要交换则执行下面的步骤
        a[c] = a[l];
        a[l] = tmp;
    }
}
// 堆排序(从小到大):  a : 待排数组;  n: 数组的长度
void HeapSortAsc(int *a, int n)
{
    int i, tmp;
    // 从(n/2 - 1) --> 0 顺序遍历,之后得到的数组实际上是一个最大二叉堆
    // 即从第一个有孩子的节点开始遍历调整,
    for (i = n / 2 - 1; i >= 0; i--) // 相当于建好一个堆
        MaxHeapDown(a, i, n - 1);

    //从最后一个元素开始对序列进行调整,直到第一个元素
    for (i = n - 1; i > 0; i--)
    {
        // 交换a[0]和 a[i],交换后a[i]是数组中最大的
        tmp = a[0];
        a[0] = a[i];
        a[i] = tmp;
        //再调整a[0>>>>i-1],使得其仍为一个最大堆
        MaxHeapDown(a, 0, i - 1);
    }
}
int main()
{
    int i;
    int a[] = {20,30,90,40,70,110,60,10,100,50,80};
    int len = (sizeof(a) / (sizeof(a[0])));
    cout << "before sort:";
    for (i = 0; i < len; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl;
    HeapSortAsc(a, len);
    cout << "after sort:";
    for (i = 0; i < len; i++)
    {
        cout << a[i] << " ";
    }
    cout << endl;
    return 0;
}

// 一个例子:寻找最小的K个数

归并排序:待更新。。。

原文地址:https://www.cnblogs.com/simplepaul/p/6755536.html