【数据结构】排序算法

大家熟知的排序方式有冒泡排序、选择排序,这两种排序方式在处理少量数据的排序时比较方便,但当数据量变大时效率明显变低。在此我们引入了新的排序方式比如:插入排序、归并排序、希尔排序、堆排序、快排。

1. 插入排序
这里写图片描述
直接插入排序:适用于数据量少且非常接近有序。(稳定)
(1)时间复杂度:最优—–已序—-O(N) / 最差—-逆序—-O(N^2)
(2)空间复杂度:O(1)

2.归并排序
这里写图片描
这里写图片描述
归并排序:稳定(没有最好最坏的情况)
(1)时间复杂度:O(NlgN)
(2)空间复杂度:O(N+lgN)=O(N)

3.希尔排序
这里写图片描述
缩小增量排序
时间复杂度:O(N^1.25) ~ O(1.6N^1.25)
空间复杂度:O(1)
不稳定

4.堆排序
使用堆结构排序
(1)升序排序:使用最大堆
这里写图片描述
(2)降序排序:使用最小堆
这里写图片描述
时间复杂度:O(NlgN)
空间复杂度:O(1)
不稳定

5.快排
快排对大量数据的排序效率很高
快排的代码实现有三种方式:
(1)从两边向中间推进法
这里写图片描述

(2)挖坑法
这里写图片描述

(3)追赶法
这里写图片描述

【Sort.h】

#include<iostream>
using namespace std;

//插入排序
void InsertSort(int *arr,int size)
{
    for (int i = 1; i < size; i++)
    {
        int key = arr[i];
        int end = i - 1;
        int j = 0;
        for (j = end; j >= 0; j--)
        {
            if (arr[j]>key)
                arr[j + 1] = arr[j];
            else
            {
                arr[j + 1] = key;
                break;
            }
        }
        arr[j + 1] = key;
    }
}
//折半插入排序
void BinaryInsert(int *arr,int size)
{
    for (int i = 1; i < size; i++)
    {
        int key = arr[i];
        int end = i - 1;
        int left = 0;
        int right = i;
        while (left < right)
        {
            int mid = left + (right - left) / 2;
            if (key<arr[mid])
                right=mid-1;             //right有可能越界,所以交换元素时用left
            else
                left=mid+1;
        }
        for (int j = i; j>right; j--)
        {
            arr[j] = arr[j-1];
        }
        arr[left] = key;
    }
}
////////////////////////////////////////////////////////////////////
//希尔排序
void ShellSort(int* arr,int size)
{
    int gap = size;
    while (gap)
    {
        gap = gap / 3 + 1;
        for (int i = 0; i < gap; i++)
        {
            for (int j = i+gap; j < size; j += gap)
            {
                if (arr[j] < arr[j - gap])
                {
                    int ret = arr[j];
                    int k = j - gap;
                    while (k>=0 && arr[k]>ret)
                    {
                        arr[k + gap] = arr[k];
                        k = k - gap;
                    }
                    arr[k + gap] = ret;
                }
            }
        }
        if (gap == 1)
            break;
    }
}


/////////////////////////////////////////////////////////////////////
//选择排序1
void SelectSort1(int *arr, int size)
{
    int i, j;
    int k = 0;
    for (i = 0; i < size - 1; i++)
    {
        k = i;
        for (j = i; j < size;j++)
        {
            if (arr[k]>arr[j])
                k = j;
        }
        swap(arr[k], arr[i]);
    }
}

void SelectSort(int* arr,int size)       //选择排序2
{
    int begin = 0;
    int end = size - 1;
    while (begin < end)
    {
        int minset = begin;
        int maxset = begin;
        for (int i = begin; i <= end; i++)
        {
            if (arr[maxset] < arr[i])
                maxset = i;
            if (arr[minset]>arr[i])
                minset = i;
        }
        if (arr[maxset]>arr[end])
            swap(arr[maxset],arr[end]);
        if (minset == end)
            minset = maxset;
        if (arr[minset]<arr[begin])
            swap(arr[minset], arr[begin]);

        begin++;
        end--;
    }
}
//////////////////////////////////////////////////////////////////////////////
int GetMidNumber(int *arr,int left,int right)
{
    if (left > right)
        return right;
    int mid = left + (right - left) / 2;
    if (arr[left] < arr[right])
    {
        if (arr[mid] < arr[left])
            return left;
        else if (arr[right] < arr[mid])
            return right;
        else
            return mid;
    }
    else 
    {
        if (arr[mid]>arr[left])
            return left;
        else if (arr[mid < arr[right]])
            return right;
        else
            return mid;
    }
}

//////////////
//快排
int position1(int*arr,int left,int right)           //左右向中推进法
{
    int begin = left;
    int end = right;
    int key = arr[end];

    while (begin<end)
    {
        while (arr[begin] <=key)
        {
            begin++;
        }
        if (begin == right)
            return right;
        while (begin!=end&&arr[end]>=key)
        {
            end--;
        }
        if (begin == end)
        {
            swap(arr[begin], arr[right]);
            return begin;
        }
        else
            swap(arr[begin], arr[end]);
    }
    return begin;
}

int position2(int *arr,int left,int right)         //追赶法
{
    int temp = GetMidNumber(arr, left, right);
    if (temp != right)
        swap(arr[temp], arr[right]);

    int key = arr[right];
    int cur = left;
    int pur = left - 1;
    while (cur!=right+1)
    {
        if (arr[cur] <key)
        {
            pur++;
            if (arr[cur] == arr[pur])
                cur++;
            else
            {
                swap(arr[cur], arr[pur]);
            }
        }
        else
        {
            cur++;
        }
    }

    if (left<right)
    swap(arr[pur + 1], arr[right]);
    pur++;
    return pur;
}

int position3(int *arr, int left, int right)       //挖坑法
{
    int key = arr[right];       //基准值
    /*int ret = GetMidNumber(arr, left, right);
    int key = arr[ret];*/
    int begin = left;
    int end = right;
    while (begin<end)
    {
        while (arr[begin] <= key)
        {
            if (end == begin)
                break;
            begin++;
        }
        if (begin == right)
            break;
        if (begin!=end)
            arr[end] = arr[begin];

        while (arr[end] > key)
        {
            if (end == begin)
                break;
            end--;
        }
        if (begin != end)
            arr[begin] = arr[end];
    }

    if (begin==end)
        arr[begin] = key;

    return begin;
}
void _QuickSort(int *arr, int left, int right)
{
    //int div = position1(arr,left,right);
    int div = position2(arr, left,right);
    //int div = position3(arr, left, right);
    if (left < right)
    {
        _QuickSort(arr, left, div-1);
        _QuickSort(arr, div + 1, right);
    }
}
void QuickSort(int* arr, int size)
{
    int left = 0;
    int right = size-1;
    _QuickSort(arr, left, right);
}
//////////////////////////////////////////////////////////////////////
//计数排序
int Range(int *arr, int size, int& max, int& min)
{
    for (int i = 0; i < size; i++)
    {
        if (arr[i]>max)
            max = arr[i];
        if (arr[i] < min)
            min = arr[i];
    }
    return (max - min+1);
}
void CountSort(int *arr, int size)            
{
    int maxData = arr[0];
    int minData = arr[0];
    int len= Range(arr, size, maxData, minData);   //len为辅助空间的长度
    int* temp = new int[len];
    memset(temp, 0, sizeof(int)*len);
    for (int i = 0; i <size; i++)
    {
        temp[arr[i] - minData]++;
    }
    int index = 0;
    for (int j = 0; j < len; j++)
    {
        while (temp[j]--)
        {
            arr[index++] = j + minData;
        }
    }
    delete[] temp;
}

///////////////////////////////////////////////////////////////////////////////
//归并排序
void Merge(int *cur,int left,int mid,int right,int *temp)
{
    int set1 = left;
    int set2 = mid;
    int set = left;
    while (set1 < mid&&set2 < right)
    {
        if (cur[set1] < cur[set2])
            temp[set++] = cur[set1++];
        else
            temp[set++] = cur[set2++];
    }
    while (set1 < mid)
    {
        temp[set++] = cur[set1];
        set1++;
    }
    while (set2 < right)
    {
        temp[set++] = cur[set2++];
    }
    memcpy(cur+left,temp+left,sizeof(int)*(right-left));
}
void _MergeSort(int* arr,int left,int right,int *temp)
{
    if (left+1 < right)                                    
    {
        int mid = left + (right - left) / 2;                     //区间是左闭右开
        _MergeSort(arr, left, mid, temp);
        _MergeSort(arr, mid, right, temp);
        Merge(arr, left, mid, right, temp);
    }
}
void MergeSort(int *array, int size)
{
    int *temp = new int[size];
    _MergeSort(array, 0, size, temp);
    delete[] temp;
}
void Display(int arr[],int size)
{
    for (int i = 0; i < size; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;
}

/////////////////////////////////////////////////////////////////////////////////
void TestSort()
{
    //int array[] = { 3, 2, 4, 1, 0, 8, 6, 7, 9, 5 };
    int array[] = { 1, 3, 5, 4, 2, 1, 3, 6, 9, 9, 6, 8, 8, 0, 0 };
    //int array[] = { 3, 4, 2, 1, 5 ,4,4,0};
    int size = sizeof(array) / sizeof(array[0]);

    CountSort(array, size);              //计数排序
    //QuickSort(array, size);              //快速排序
    //SelectSort1(array, size);          //插入排序1
    //ShellSort(array, size);            //希尔排序
    //BinaryInsert(array, size);         //折半插入排序
    //InsertSort(array, size);           //插入排序2
    //MergeSort(array,size);            //归并排序
    //SelectSort(array, size);          //选择排序
    Display(array, size);
}

【test.c】

#include"Sort.h"

int main()
{
    TestSort();
    system("pause");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值