关闭

基本排序算法

181人阅读 评论(0) 收藏 举报
分类:

代码:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

/*---------------------------改进冒泡排序------------------------------------*/
// 算法复杂度O(n^2)
vector<int> BubbleSort(vector<int> vec)
{
    int length = vec.size();
    bool flag = true;   //避免在剩余的数已经有序的情况下做无意义的循环判断
    for (int i = 0; i < length; i++)
    {
        flag = false;
        for (int j = length - 1; j > 0;j--)
        {
            if (vec[j] < vec[j-1])
            {
                swap(vec[j], vec[j -1]);
                flag = true;            //如果有数据交换,则flag为true
            }
        }
    }
    return vec;
}

//简单选择排序, 算法复杂度O(n^2)
vector<int> SimpleSelectionSort(vector<int> vec)
{
    int length = vec.size();
    int min = 0;        //保存每次找到的最小值的下标
    for (int i = 0; i < length-1; i++)
    {
        min = i;
        for (int j = i + 1; j < length; j++)
        {
            if (vec[j] < vec[min])
            {
                min = j;
            }
        }

        if (i != min)
            swap(vec[i], vec[min]);

    }

    return vec;
}


/*---------------------------简单插入排序------------------------------------*/
// 算法复杂度O(n^2)

vector<int> SimpleInsertSort(vector<int> vec)
{
    int length = vec.size();
    for (int i = 1, j = 0; i < length; i++)
    {
        if (vec[i] < vec[i - 1])
        {
            int temp = vec[i];
            for (j = i - 1; j >= 0 && vec[j] > temp; j--)
            {
                vec[j + 1] = vec[j];
            }
            vec[j + 1] = temp;
        }
    }
    return vec;
}

/*---------------------------希尔排序------------------------------------*/
//不稳定排序,算法复杂度O(n^(3/2))
vector<int> ShellSort(vector<int> vec)
{
    int j = 0;
    int increment = vec.size();
    do 
    {
        increment = increment / 3 + 1;
        for (int i = increment; i < vec.size() ; i++)
        {
            if (vec[i] < vec[i - increment])
            {
                int temp = vec[i];
                for (j = i - increment; j >= 0 && temp < vec[j];j -= increment)
                {
                    vec[j + increment] = vec[j];
                }
                vec[j + increment] = temp;
            }           
        }
    } while (increment > 1);
    return vec;
}

/*---------------------------堆排序------------------------------------*/

//堆排序,不稳定排序算法,时间复杂度为O(nlogn)
//不适合排序序列个数较少的情况,开始建堆所需的比较次数较多

void swap(vector<int> &temp, int head, int last)    //交换堆顶与未经排序子序列的最后一个结点
{
    int tmp = temp[head];
    temp[head] = temp[last];
    temp[last] = tmp;
}
void HeapAdjust(vector<int> &vec, int low, int high)
{
    int temp = vec[low];
    for (int j = low * 2; j <= high; j *= 2)
    {
        if (j < high && vec[j] < vec[j + 1])
            j++;
        if (temp >= vec[j])
            break;
        vec[low] = vec[j];
        low = j;
    }
    vec[low] = temp;  
}
vector<int> HeapSort(vector<int> vec)
{
    vector<int> temp(vec.size() + 1, 0);
    temp[0] = -1;
    for (int i = 0; i < vec.size(); i++)
    {
        temp[i + 1] = vec[i];
    }

    //构建大根堆
    for (int i = vec.size() / 2; i > 0; i--)
    {
        HeapAdjust(temp, i, vec.size());
    }

    //堆排序
    for (int i = vec.size(); i > 1; i--)
    {
        swap(temp, 1, i);
        HeapAdjust(temp, 1, i-1);
    }

    for (int i = 1; i < temp.size();i++)
    {
        vec[i - 1] = temp[i];
    }


    return vec;
}

/*---------------------------归并排序,递归实现------------------------------------*/
//合并
void Merge(vector<int>& subvec, int p, int mid, int q)
{
    int a = mid - p + 1;
    int b = q - mid;
    vector<int> L(a + 1, 0);
    vector<int> R(b + 1, 0);
    for (int i = 0; i < a; i++)
        L[i] = subvec[p + i];
    for (int j = 0; j < b; j++)
        R[j] = subvec[mid + j + 1];
    L[a] = R[b] = INT_MAX;

    int i = 0, j = 0;
    for (int k = p; k < q + 1; k++)
    {
        if (L[i] <= R[j])
        {
            subvec[k] = L[i];
            i++;
        }
        else
        {
            subvec[k] = R[j];
            j++;
        }
    }
}

//分解
void RSort(vector<int> &subvec, int p, int q)
{
    if (p < q)
    {
        int mid = (p + q) / 2;
        RSort(subvec, p, mid);
        RSort(subvec, mid + 1, q);
        Merge(subvec, p, mid, q);       //合并

    }
}
vector<int> MergeSort(vector<int> vec)
{
    int length = vec.size();
    RSort(vec,0,length-1);          //分解为多个子问题求解,分治思想
    return vec;
}

/*---------------------------归并排序,非递归实现------------------------------------*/

//将有序的v1[i...m]和有序的v1[m+1...n]归并到有序的v2中
void Merge2(vector<int>& v1, vector<int>& v2, int i, int m, int n)
{
    int k = 0, j = 0;
    for (k = i, j = m + 1; i <= m && j <= n; k++)
    {
        if (v1[i] < v1[j])

            v2[k] = v1[i++];
        else

            v2[k] = v1[j++];
    }

    if (i <= m)
    {
        for (int t = 0; t <= m - i; t++)
            v2[k+t] = v1[i+t];
    }
    if (j <= n)
    {
        for (int t = 0; t <= n-j; t++)
            v2[k+t] = v1[j+t];
    }
}

//将v1中相邻长度为gap的子序列两两归并到v2中

void MergeAdjacent(vector<int>& v1, vector<int>& v2, int gap, int len) 
{
    int i = 0;
    while (i <= len-2*gap)
    {
        Merge2(v1, v2, i, i + gap - 1, i + 2 * gap - 1);
        i += 2 * gap;
    }

    if (i < len - gap + 1 )         //当不够两组进行归并时,如果剩余元素超过k个元素,仍然进行归并
        Merge2(v1, v2,i, i + gap - 1, len-1);
    else                            //如果剩余元素不超过k个元素时,直接复制给中间数组
    {
        for (int j = i; j < len; j++)
        {
            v2[j] = v1[j];
        }

    }

    for (i = 0; i < len; i++)
        v1[i] = v2[i];
}
vector<int> MergeSort2(vector<int> vec)
{
    int length = vec.size();
    vector<int> vec2(length, 0);
    int k = 1;
    while (k < length)
    {
        MergeAdjacent(vec, vec2, k, length);
        k = 2 * k;
    }
    return vec;
}

/*---------------------------快速排序------------------------------------*/

int Partition(vector<int>& vec, int low, int high)
{
    int pivotkey = vec[low];    //用子表中的第一个元素作为枢轴
    while (low < high)
    {
        while (vec[high] >= pivotkey && low < high)
            high--;
        swap(vec[low], vec[high]);
        while (vec[low] <= pivotkey && low < high)
            low++;
        swap(vec[low], vec[high]);
    }

    return low;
}
void QSort(vector<int>& vec, int low, int high)
{
    int pivot;
    if (low < high)
    {
        pivot = Partition(vec, low, high);  //算出中枢值
        QSort(vec, low, pivot - 1);
        QSort(vec, pivot + 1, high);
    }

}
vector<int> QuickSort(vector<int> vec)
{
    int length = vec.size();
    QSort(vec, 0, length - 1);
    return vec;
}

/*---------------------------计数排序------------------------------------*/

//算法复杂度O(n),线性时间排序算法,适合于小范围的集合的排序
vector<int> CountSort(vector<int> vec)
{
    int length = vec.size();
    vector<int> result(length,0);   //保存结果

    int max;    //保存最大值
    //找出vec中的最大值
    if (length > 0)
    {
         max = vec[0];
        for (int i = 1; i < length; i++)
        {
            if (max < vec[i])
                max = vec[i];
        }
    }

    //创建保存计数的vector
    vector<int> temp(max + 1, 0);

    //保存最后结果
    //vector<int> result;
    for (int i = 0; i < length;i++)
    {
        temp[vec[i]] += 1;
    }

    //temp[i] 包含了小于等于i的个数,以确定i的位置
    for (int i = 1; i <= max;i++)
    {
        temp[i] += temp[i - 1];
    }

    for (int j = length - 1; j >= 0;j--)
    {
        result[temp[vec[j]]-1] = vec[j];
        temp[vec[j]] = temp[vec[j]] - 1;
    }
    return result;

}

/*---------------------------改进的计数排序------------------------------------*/
//与标准的相比,可以节约一些空间,
vector<int> CountSort2(vector<int> vec)
{
    int length = vec.size();


    int max;    //保存最大值
    //找出vec中的最大值
    if (length > 0)
    {
        max = vec[0];
        for (int i = 1; i < length; i++)
        {
            if (max < vec[i])
                max = vec[i];
        }
    }

    //创建保存计数的vector
    vector<int> temp(max + 1, 0);

    for (int i = 0; i < length; i++)
    {
        temp[vec[i]] += 1;
    }

    int j = 0;
    for (int i = 0; i <= max; i++)
    {
        while (temp[i]--)
            vec[j++] = i;
    }


    return vec;
}

/*---------------------------基数排序------------------------------------*/

//算法时间复杂度O(n),具有线性的时间代价
//计数排序有两种方式,LSD由数值的最右边(低位)开始,而MSD则相反,由数值的最左边开始
//LSD适用于位数少的数值,如果位数多,MSD的效率更好
/*
MSD实现是一个递归的过程:
(1)首先根据最高位的关键码K1排序,得到若干个对象组,即分到若干个桶中,每个桶中有相同的关键字
(2)再分别对每个桶根据关键码K2进行排序,再根据K2的分成若干个子桶,依次类推...
(3)最后把所有桶中的序列连接起来既构成了一个有序的序列
*/

//这里实现LSD,MSD类似
//获取x这个数的第d位的数字
//因为LSD由数值的最右边开始的,123的第1位为3,第二位为2,...
int getDigit(int x, int d)
{
    int a[] = { 1, 1, 10, 100 };    //本例中,最大数是百位数,因此a[]中最大为100
    return (x / a[d] % 10);
}

vector<int> RadixSortLSD(vector<int> vec)
{
    int length = vec.size();
    int d = 3;      //本例中,最大的只有3位数
    int count[10];  //每个桶排序
    int j;

    int* bucket = new int[length];

    //对每位进行排序
    for (int k = 1; k <= d; k++)
    {
        for (int i = 0; i < 10; i++)     //利用计数排序的思想用数组模拟桶
            count[i] = 0;

        //统计各个桶中所盛数据个数
        for (int i = 0; i < length; i++)
        {
            count[getDigit(vec[i], k)]++;
        }

        for (int i = 1; i < 10; i++)    
        {
            count[i] += count[i - 1];   
        }
        //这时,count[i]表示第i个桶的右边界索引
        for (int i = length - 1; i >= 0; i--)
        {
            j = getDigit(vec[i], k);
            bucket[count[j] - 1] = vec[i];
            count[j]--;
        }

        //此时,count[i]为第i个桶的左边界

        //将桶中的数据收集出来
        for (int i = 0, j = 0; i < length; i++, j++)
            vec[i] = bucket[j];

    }

    delete[] bucket;

    return vec;
}

int main()
{
    vector<int> array = { 9, 1, 5, 8, 3, 7, 4, 6, 2 };
    vector<int> result;

    //冒泡排序
    result = BubbleSort(array);
    cout << "冒泡排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl << endl;

    //选择排序
    result = SimpleSelectionSort(array);
    cout << "简单选择排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl << endl;

    //插入排序
    result = SimpleInsertSort(array);
    cout << "简单插入排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl << endl;

    //希尔排序
    result = ShellSort(array);
    cout << "希尔排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl << endl;


    //堆排序
    result = HeapSort(array);
    cout << "堆排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl << endl;

    //归并排序,递归实现
    result = MergeSort(array);
    cout << "(递归实现)归并排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl<<endl;

    //归并排序,非递归实现
    result = MergeSort2(array);
    cout << "(非递归实现)归并排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl << endl;

    //快速排序
    result = QuickSort(array);
    cout << "快速排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl<<endl;

    //计数排序
    result = CountSort(array);
    cout << "计数排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl << endl;

    //计数排序2
    result = CountSort2(array);
    cout << "改进的计数排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl << endl;

    //基数排序
    vector<int> array2 = { 329, 457, 657, 83, 436, 720, 355, 221, 983};
    cout << "基数排序前: ";
    for (auto it = array2.begin(); it != array2.end(); it++)
        cout << *it << " ";
    cout << endl;
    result = RadixSortLSD(array2);
    cout << "LSD基数排序后: ";
    for (auto it = result.begin(); it != result.end(); it++)
        cout << *it << " ";
    cout << endl << endl;

    system("pause");
    return 0;
}

测试:

这里写图片描述

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:55223次
    • 积分:2791
    • 等级:
    • 排名:第13605名
    • 原创:222篇
    • 转载:97篇
    • 译文:0篇
    • 评论:3条
    最新评论