7种排序算法

1.冒泡排序

#include "bubblesort.h"


bool compare(const int &a , const int &b)
{
    return a < b;
}
// 暴力冒泡:效率低下,交换
void bubbleSort0(vector<int> &a)
{
    for(int k=0;k<10000;++k)
    {
        int len = a.size();
        for(int i=0;i<len-1;++i)
        {
            for(int j =i+1;j<len;++j)
            {
                if(a[i]>a[j])
                {
                    int temp = a[i];
                    a[i] = a[j];
                    a[j] = temp;
                }
            }
        }
    }
}

// 正常冒泡:两两交换
void bubbleSort1(vector<int> &a)
{
    for(int k=0;k<10000;++k)
    {
        int len = a.size();
        for(int i=0;i<len;++i)
        {
            for(int j = len-2;j>=i;--j)
            {
                if(a[j]>a[j+1])
                {
                    int temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                }
            }
        }
    }
}
// 改进冒泡:设置flag;一次交换都没发生,表明已经有序,此时退出循环
void bubbleSort2(vector<int> &a)
{
    for(int k=0;k<10000;++k)
    {
        int len = a.size();
        bool flag = true;
        for(int i=0;i<len && flag;++i)
        {
            flag = false;
            for(int j = len-2;j>=i;--j)
            {
                if(a[j]>a[j+1])
                {
                    int temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                    flag = true;
                }
            }
        }
    }
}

2.选择排序

#include "selectsort.h"

void SelecSort(vector<int> &a)
{
    int len = a.size();
    for(int i=0;i<len-1;++i)
    {
        int min = i;
        // 找出这一轮的最小值的下标
        for(int j=i+1;j<len;++j)
        {
            if(a[min]>a[j])
                min = j;
        }
        // 最小值放在i这个位置
        if(min!=i)
        {
            int temp = a[i];
            a[i] = a[min];
            a[min] = temp;
        }
    }
}

3.插入排序

#include "insertsort.h"

void InsertSort(vector<int> &a)
{
    for(int k=0;k<10000;++k)
    {
        int len = a.size();
        for(int i=1;i<len;++i)
        {
            if(a[i]<a[i-1])
            {
                // 在i的左边,将大于a[i]的右移一位
                // 设置哨兵的方法
                int temp = a[i];
                int j=i-1;
                for(;j>=0 && a[j] > temp;--j)
                    a[j+1] = a[j];
                a[j+1] = temp;
                // 上述思路的我的实现
//                for(int j=i-1;j>=0;--j)
//                {
//                    if(a[j+1]<a[j])
//                        swap(a[j],a[j+1]);
//                    else
//                        break;
//                }
            }
        }
    }

}

4.希尔排序

#include "shellsort.h"
void shellsort(vector<int> &a)
{
    for(int k=0;k<10000;++k)
    {
        int len = a.size();
        int increment = len;
        do
        {
            increment = increment/3 +1;
            for(int i= increment;i<len;++i)
            {
                //方法一:我的交换法
                for(int j = i;j>=increment;j=j-increment)
                {
                    if(a[j]<a[j-increment])
                        swap(a[j],a[j-increment]);
                    else
                        break;
                }

//                // 方法二:哨兵法,和插入排序类似
//                int temp = a[i];
//                int j = i-increment;
//                for(;j>=0 && a[j]>temp;j=j-increment)
//                    a[j+increment] = a[j];
//                a[j+increment] = temp;
            }
        }while(increment>1);
    }
}

5.堆排序

#include "heapsort.h"

void HeapSort(vector<int> &a)
{
    for(int k=0;k<10000;++k)
    {
        // 构造一个大顶堆,n/2个非叶子节点
        int i = a.size()/2;
        for(;i>0;--i)
            HeapAdjust(a,i,a.size());

        for(i=a.size();i>1;--i)
        {
            // 大顶堆,a[0]是最大值,将其换到末尾去,然后a[i-1]值从大顶堆中去除
            swap(a[0],a[i-1]);
            // 从a[0]到a[i-2]再重新构建大顶堆,
            // 1表示大顶堆中的根节点,对应数组a[0];i-1对应最后一个叶子节点,对应a[i-2],
            HeapAdjust(a,1,i-1);
        }
    }
}
// 构造大顶堆,有很多-1是因为数组下标从0开始。
// j表示其在完全二叉树中的按层遍历的位置,2j是左孩子,2j+1是右孩子,所以j的值最好不变
void HeapAdjust(vector<int> &a ,int s,int m)
{
    int temp = a[s-1];
    int j = 2*s;
    // 一直向下交换根
    for(;j<=m;j*=2)
    {
        // j=m说明没有右孩子
        if(j<m && a[j-1]<a[j+1-1])
            ++j;
        // 根已经大于左右孩子
        if(temp>=a[j-1])
            break;

        a[s-1] = a[j-1];
        s = j;
    }
    a[s-1] = temp;
}

6.归并排序

#include "mergesort.h"

void MergeSort(vector<int> &a)
{
    for(int k =0;k<10000;++k)
        Msort(a,0,a.size()-1);
}

void Msort(vector<int> &a , int left , int right)
{
    if(left < right)
    {
        int m = left+(right-left)/2;
        Msort(a,left,m);
        Msort(a,m+1,right);
        //将左右两块排好序的,再归并一下,变成一个有序的
        Merge(a,left,m,right);
    }
}

void Merge(vector<int> &a ,int left, int m, int right)
{
    // 上述有递归过程,b的大小应为每次递归的对应容量
    vector<int> b(right-left+1,0);
    int i = left;
    int j = m+1;
    int k = 0;
    for(;i<=m && j<=right ; ++k)
    {
        if(a[i] < a[j])
            b[k] = a[i++];
        else
            b[k] = a[j++];
    }
    while(i<=m)
    {
        b[k++] = a[i++];
    }

    while(j<=right)
    {
        b[k++] = a[j++];
    }

    // 在与b相应的位置更新排好序的a
    for(int num = 0;num<right-left+1;++num)
    {
        a[left+num] = b[num];
    }
}

7.快速排序

#include "quicksort.h"

void QuickSort( vector<int> &a)
{
    for(int k=0;k<1000000;++k)
    {
        Qsort(a, 0,a.size()-1);
        // 优化递归
        //Qsort1(a, 0,a.size()-1);
    }
}

void Qsort(vector<int> &a, int left ,int right)
{
    int pivot = 0;
    if(left < right)
    {
        //pivot = Partition(a,left,right);
        pivot = Partition1(a,left,right);
        Qsort(a,left,pivot-1);
        Qsort(a,pivot+1,right);
    }
}

// 优化递归
void Qsort1(vector<int> &a, int left ,int right)
{
    int pivot = 0;
    while(left < right)
    {
        //pivot = Partition(a,left,right);
        pivot = Partition1(a,left,right);
        Qsort1(a,left,pivot-1);
        left = pivot+1;
    }
}

int Partition(vector<int> &a, int left,int right)
{
    int pivotkey = a[left];
    while(left < right)
    {
        while(left < right && a[right] >= pivotkey)
            --right;
        swap(a[left],a[right]);

        while(left < right && a[left] <= pivotkey)
            ++left;
        swap(a[left],a[right]);
    }
    return left;
}

//优化pivotkey(三数取中),优化不必要交换
int Partition1( vector<int> &a, int left ,int right)
{
    int m = left + (right-left)/2;
    if(a[left] > a[right])
        swap(a[left],a[right]);//左端较小

    if(a[m] > a[right])
        swap(a[m],a[right]);//中间较小

    if(a[m] > a[left])
        swap(a[left],a[m]);//a[left]取左边和中间的大者

    int pivotkey = a[left];
    while(left < right)
    {
        //找右边第一个小于pivotkey的
        while(left < right && a[right] >= pivotkey)
            --right;
        a[left] = a[right];

        // 找左边第一个大于pivotkey的
        while(left < right && a[left] <= pivotkey)
            ++left;
        a[right] = a[left];
    }
    a[left] = pivotkey;
    return left;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值