各种排序算法小结和实现

各种排序算法想必大家都不陌生,定义我就不多介绍了,直接写下自己的一些小结。

快速排序:可以算的上应用最广的排序算法。其排序思路是随机选取一个数字作为标志,使得小于它的数在它左边,大于它的数在它的右边,然后递归对两边的数据排序。
归并排序:应用分之的思想,先将要排序的分为两列,然后分别进行排序,然后合并到另一
个数组中,最后再进行把它复制回来。
冒泡排序:是稳定排序,适用于排列的数组较小而且基本有序,否则时间复杂度太高。
选择排序:和冒泡排序差不多,差别是冒泡是相邻的比较,最后选出最大的或者最小的,选
择排序是选一个点,然后把遍历把最小的和这个替换,两个思想差不多,但选择排序是不稳定排序,选择排序理论和实际上是比冒泡要快的。
插入排序:对于部分有序的数组这种算法很有用,因为有可能达到O(n)复杂度,但是一般的
话还是O(n*n)。
希尔排序:插入排序的变种,我们知道,插入排序它对数组无序太慢了,而且每次交换移动
一次太慢了,于是设计希尔排序,它每次移动的步长(h)是可变的,一般有一个那样的数组,可以存步 长,然后先h有序,再h/3有序,再h/3/3有序,最后1有序,此处的h/3只是一个设计,也可以用其它的。希尔排序很快,在数据量很大的情况下,比快速排序也就慢一倍,但是它不需要额外的空间。
堆排序: 对于从很多数据中选择几个最大的,不用完全排序就可以选出来,而且消耗的时
间和空间有个折衷。例如说从10亿个数据中选10个最大的,只需维护一个10大小的堆,然后每次添加数据将大于10的用堆删除就行了,消耗的时间复杂度为 O(n*logM),M为个数大小,此处为10,空间复杂度为M.
基数排序:有两种,一种从低位到高位,另一种从高位到低位,先按一位的大小排在一个桶
里,然后在排后面的位。

废话不多说,直接上代码。

// sort.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <algorithm>
using namespace std;

//冒泡排序
void BubbleSort(int *arr, int length)
{
    cout << "bubble sort:" << endl;
    if (arr==NULL||length <= 0)
        return;
    for (int i = length - 1; i > 0; i--)
        for (int j = 0; j < i; j++)
            if (arr[j]>arr[j + 1])
                swap(arr[j], arr[j + 1]);
}

//选择排序
void SelectSort(int *arr, int length)
{
    cout << "select sort: " << endl;
    if (length <= 0)
        return;
    for (int i = 0; i < length - 1;i++)
        for (int j = i; j < length - 1; j++)
        {
        if (arr[j] < arr[i])
            swap(arr[i], arr[j]);
        }
}

//网上看的选择排序的实现,比自己没有那么多次交换,人是每次都记录最小的所在的位置,每次都更新位置,最后找到一个最小的再交换,比我的优化多了
template <class T>
void selection_sort(T a[], int n)
{ // 不稳定; 反例: { 2, 2, 1 }
    int min;
    for (int i = 0; i < n - 1; ++i) { // 最多做n-1趟排序
        min = i; // 先假设a[i]最小
        for (int j = i + 1; j < n; ++j) // 在当前无序区a[i:n-1]中查找最小值
            if (a[j] < a[min])
                min = j; // min记下当前无序区最小值所在位置
        if (min != i) // 找到比当前a[i]更小者
            std::swap(a[i], a[min]);
    }
}

//插入排序
void InsertSort(int *arr, int length)
{
    cout << "insert sort: " << endl;
    if (arr == NULL || length < 0)
        return;
    for (int i = 1; i < length; i++)
    {
        for (int j = i; j > 0; j--)
        {
            if (arr[j]<arr[j - 1])
                swap(arr[j], arr[j - 1]);
            else
                break;
        }
    }
    return;
}

//希尔排序,其实就是插入排序的变种,但是比插入排序快多了
void ShellSort(int *arr, int length)
{
    cout << "shell sort: " << endl;
    int h = 1;
    while (h < length / 3)  h = 3 * h + 1;   //1,4,13,40,121,364,1093...其实这个数组是科学家设计出来的,我们只需用就行了,一般程序中可以直接用一个数组将这些值放入
    while (h >= 1)
    {
        for (int i = h; i < length; i++)
        {
            for (int j = i; j >= h&&arr[j] < arr[j - h]; j -= h)
                swap(arr[j], arr[j - h]);
        }
        h = h / 3;//先h有序,再h/3有序,再h/3/3有序,最后1有序
    }

}

//堆排序
void sink(int *arr, int start, int end);
void HeapSort(int *arr, int length)
{
    cout << "heap sort: " << endl;
    for (int k = length / 2; k >= 0; k--)
        sink(arr, k, length-1);
    length--;
    while (length > 0)
    {
        swap(arr[0], arr[length--]);
        sink(arr, 0, length);
    }
}

void sink(int *arr, int start, int end)
{
    while (2*start+1<=end)
    {
        int j = 2 * start + 1;
        if (j<end&&arr[j]<arr[j + 1]) j++;          //此处调了两个小时,,,,注意如果首先是选最大值,先试着选出两个儿子中的最大值,再和他们的最大值交换,开始没想到。。。。
        if (arr[start] > arr[j])
            break;
        swap(arr[start], arr[j]);
        start = j;
    }
}

//基数排序
int bit(int *arr, int length);
void RadixSort(int *arr, int length)
{
    cout << "radix sort: " << endl;
    int d = bit(arr, length);
    int *tmp = new int[length];
    int *count = new int[10];
    int i,k,begin=1;
    while (d > 0)
    {
        for (i = 0; i < 10; i++)
            count[i] = 0;
        for (i = 0; i < length; i++)
        {
            k = (arr[i] / begin) % 10;
            count[k]++;
        }
        for (i = 1; i < 10; i++)
        {
            count[i] = count[i - 1] + count[i];
        }
        for (i = 0; i < length; i++)
        {
            k = (arr[i] / begin) % 10;
            tmp[count[k]-1] = arr[i];
            count[k]--;
        }
        for (i = 0; i < length; i++)
            arr[i] = tmp[i];
        begin *= 10;
        d--;
    }
    delete[] tmp;
    delete[] count;
}

int bit(int *arr, int length)
{
    int d = 1,k=10;
    for (int i = 0; i < length; i++)
    {
        while (arr[i]>=k)
        {
            d++;
            k *= 10;
        }
    }
    return d;
}

//归并排序
void MergeSort(int *arr,int left, int right);
void Merge(int* arr, int left, int mid, int right);
void MergeSort(int *arr, int length)
{
    cout << "merge sort: " << endl;
    if (arr == NULL || length < 0)
        return;
    MergeSort(arr, 0, length - 1);
}

void MergeSort(int *arr, int left, int right)
{
/*  if (left >= right)
        return;
    if (right - left == 1)
    {
        if (arr[right] < arr[left])
            swap(arr[left], arr[right]);
        return;
    }*/
    if (left < right)
    {
        int mid = left + (right - left) / 2;
        MergeSort(arr, left, mid);
        MergeSort(arr, mid + 1, right);
        Merge(arr, left, mid, right);
    }
}

void Merge(int* arr, int left, int mid, int right)
{
    int *temp = new int[right  + 1];         //不能直接定义一个静态数组,因为编译的时候没传具体数组大小不好分配空间,故此处用动态数组,开始这里错了,折腾好久
    for (int i = left; i <= right; i++)
    {
        temp[i] = arr[i];
    }
    int i = left, j = mid + 1,index=left;
/*  for (int k = left; k <= right; k++)
    {
        if (i > mid) arr[k] = temp[j ++];
        else if (j > right) arr[k] = temp[i++];
        else if (temp[i] < temp[j])  arr[k] = temp[i++];
        else
            arr[k] = temp[j++];
    }*/
    while (index <= right)
    {
        if (i>mid)
            arr[index++] = temp[j++];
        else if (j > right)
            arr[index++] = temp[i++];
        else if (temp[i] > temp[j])
            arr[index++] = temp[j++];
        else
            arr[index++] = temp[i++];
    }
    delete [] temp;
}

//快速排序
void QuickSort(int *arr, int length, int left, int right);
int partion(int *arr,int length, int left, int right);
void QuickSort(int *arr, int length)
{
    cout << "quick sort: " << endl;
    QuickSort(arr,length, 0, length - 1);
}

void QuickSort(int *arr,int length, int left, int right)
{
    if (right == left)              //此处用right<=left,不行,输入length为负值时到不了partion异常处理部分,不终止
        return;
    int i = partion(arr,length, left, right);
    if (i > left)
        QuickSort(arr, length,left, i - 1);
    if (i < right)
        QuickSort(arr, length,i + 1, right);
}

int partion(int *arr, int length, int left, int right)
{
    if (arr == NULL || length <= 0 || left < 0 || right >= length)
    {
        cerr<<"invalid input"<<endl;
        exit(1);
    }
    srand(time(NULL));
    int i = (rand() % (right+1-left))+left;
    swap(arr[i], arr[right]);
    int start = left - 1;
    int index = left;
    for (index = left; index <= right; index++)
    {
        if (arr[index] < arr[right])
        {
            start++;
            if (start != index)
                swap(arr[start], arr[index]);
        }
    }
    start++;
    swap(arr[start], arr[right]);
    return start;
}

void print(int *arr, int length)
{
    for (int i = 0; i < length; i++)
        cout << arr[i] << " ";
    cout << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    int array[10] = { 3, 4, 6, 1, 2, 7, 8, 9, 5, 0 };
//  BubbleSort(array, 10);
//  MergeSort(array, 10);
//  QuickSort(array, 10);
//  InsertSort(array, 10);
//  ShellSort(array, 10);
//  HeapSort(array, 10);
    RadixSort(array, 10);
    print(array, 10);
    return 0;
}

自己从几个方面对各个排序算法性能做一个比较,因为第一次写博客,不会画表格,只好截个图拿上来了。。。图片上传不清晰,可以打开新的标签页看大图。
这里写图片描述

总结:对于较大的数组,且不要求稳定的排序,可以考虑用快速排序;
而对于要求稳定的排序,则考虑归并排序;
对于较小的数组,且有序,可以考虑选择排序和插入排序;
堆排序对于从众多数据中选择几个优的在时间和空间上有个折衷。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值