八大排序

1冒泡排序

void bubble_sort(int *arr, int len)
{
    bool flag = true;
    for (int i = 0; i < len - 1 && flag; ++i)//排序的趟数;最后一个不用再向后比较
    {
        flag = false;//标志位,看上一轮是否还在交换,若没有进入交换则flag=false说明都已经排好,无需再走一趟,直接跳出循环。
        for (int j = 0; j < len - 1 - i; ++j)//每一趟排序找出最大的;排除最后已经排序好的
        {
            if (arr[j] > arr[j + 1])//相邻交换,将最大的放在最后一个位置
            {
                flag = true;
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }
}

2.选择排序

void select_sort(int *arr, int len)//从小到大
{
    int min = arr[0];
    int min_index = 0;
    int i = 0;
    int j = 0;
    for (i = 0; i < len - 1; ++i)
    {
        min = arr[i];//放最小值
        min_index = i;//放最小值的下标
        for (j = i + 1; j < len; ++j)//一次循环找出最小数的数值和下标且和arr[i]交换
        {
            if (min > arr[j])//拿arr[i]与一趟的j比较,找出最小的赋给临时量
            {
                min = arr[j];
                min_index = j;
            }
        }
        if (i != min_index)//最后只做一次交换
        {
            int tmp = arr[i];
            arr[i] = arr[min_index];
            arr[min_index] = tmp;
        }
    }
}

3、插入排序

void insert_sort(int *arr, int len)
{
    int j = 0;
    int tmp = 0;   //
    for (int i = 1; i < len; ++i)//第一趟只有一个数,不需要比较
    {
        tmp = arr[i];   //arr[i]==arr[j+1],也就是将下面的arr[j+1]赋给tmp
        for (j = i - 1; j >= 0; --j)//arr[i]从arr[i-1]开始逆向比较
        {
            if (arr[j] < tmp)//遇到比自己小的为止
            {
                break;
            }
            arr[j + 1] = arr[j];//比自己大的值后移
        }
        arr[j + 1] = tmp;//插入合适位置
    }
}

时间复杂度:O(N^2)
空间呢复杂度:O(1)
稳定(不跳跃的比较)
针对于数据量较小,基本有序O(N)
分组多次插入排序-》希尔
4、希尔排序

static void shell(int *arr, int len, int gap)//insert_sort()的变形,insert_sort()一数一组
{
    int j = 0;
    int tmp = 0;
    for (int i = gap; i < len; ++i)//gap个为一组
    {
        tmp = arr[i];
        for (j = i - gap; j >= 0; j-=gap)
        {
            if (arr[j] < tmp)
            {
                break;
            }
            arr[j + gap] = arr[j];
        }
        arr[j + gap] = tmp;
    }
}

void shell_sort(int *arr, int len)
{
    shell(arr, len, 3);//多次分组。提高效率,使得数逐渐基本有序
    shell(arr, len, 1);
}
void shell_sort(int *arr, int len)
{
    int d[]={5,3,1};//宽度
    for(int i=0;i<3;i++)
    {
        shell(arr,len,d[i]);
    }
}

分组,岔开分
空间复杂度:O(1)
时间复杂度:O(N^1.3–1.5)
不稳定(跳跃式交换数据)
5、堆排序
首先第一步: 初始化大顶堆(从最后一个有子节点开始往上调整最大堆)
1、建堆的过程是从最后一个子树开始(最下面),然后排序开始,首尾交换
2、每次调整都是从这个要调整的子树的根位置开始
若:父:i
则:左孩子:2*i+1 右孩子:2*i+2
若:左孩子:i 右孩子i+1
则父:(i-1)/2
时间复杂度:o(nlogn)
时间复杂度:o(1)
不稳定
若数据为有序:时间复杂度还是一样的

void adjust(int *arr,int len,int index)
{
    int left=index*2+1;
    int right=index*2+2;
    int max=index;

    if(left<len && arr[left]>arr[max])
        max=left;
    if(right<len && arr[right]>arr[max])
        max=right;
    if(max ==index)
    {
        swap(arr[max],arr[index]);
        adjust(arr,len,max);
    }
}

void head_sort(int* arr,int size)
{
    for(int i=size/2-1;i>=0;i++)
    {
        adjust(arr,size,i);
    }
    for(int i=size-1;i>=1;i--)
    {
        swap(arr[0],arr[i]);
        adjust(arr,i,0);
    }
}

6、快排(不稳定)
递归版:

static int partition(int *arr ,int left, int right)
{
    int tmp = arr[left];
    while (left < right)//直到left和right重合,此时合适位置找到
    {
        while (arr[right] > tmp && left < right)
        {
            right--;
        }
        arr[left] = arr[right];

        while (arr[left] < tmp && left < right)
        {
            left++;
        }
        arr[right] = arr[left];
    }
    arr[left] = tmp;//合适位置赋值
    return left;
}

static void quick(int *arr, int left, int right)
{
    if (left < right)
    {
        //将arr[left]放到合适位置,将枢轴返回出来,pivot左侧的都小于arr[left],右侧的都大于
        int pivot = partition(arr, left, right);
        quick(arr, left, pivot - 1);//枢轴两侧开始递归
        quick(arr, pivot + 1, right);
    }
}

void quick_sort(int *arr, int len)//递归快速排序
{
    quick(arr, 0, len - 1);
}

非递归快排:(重要!)
先操作左边,右边先放里面
栈应该开辟多大呢?sizeof(int)* 2 *(logn+1);

void quick_sort(int *arr,int low,int high)
{
    stack<int> st;
    int k;
    if(low<high)
    {
        st.push(low);
        st,push(high);
        while(!st.empty())
        {
            int i=st.top();
            st.pop();
            int j=st.top();
            st.pop();

            k=partition(arr,i,j);

            if(i<k-1)
            {
                st.push(i);
                st.push(j);
            }
            if(k+1<j)
            {
                st.push(k+1);
                st.push(j)
            }

        }
    }
}

时间复杂度:O(nlogn)log以2为底的n
空间复杂度:O(logn)
快排优化:
1,如果前面的有序,那我们就白白把前面的走了一遍———》用随机数随便取一个下标开始
2,三者取中
3,有大量的重复数据——》放一起-》先放两边-》再放周围
4,快有序时,用插入排序
5,使用并行或多线程

7,归并:

void merge(int* arr,int left,int mid,int right)       //放到一个新数组中
{
    int aux[right-left+1];                       //拷贝到新数组中
    for(int m=left;m<=right;++m)
    {
        aux[i]=arr[i];
    }

    int i=left,j=mid+1;
    for(int k=left;i<=mid && j<=right;++k)     //归并
    {
        if(aux[i]<=aux[j])  arr[k]=aux[i++];      //哪边小,把哪边放入数组
        else if(aux[i>aux[j])   arr[k]=arr[j++];

        else if(i>mid)  arr[k]=aux[j++];       //一边完了
        else if(j>right) arr[k]=aux[i++];
    }
}

void mergesort(int *arr,int left,int right)
{
    if(left>=right)
        return ;
    int mid=(right+left)/2;
    mergesort(arr,left,mid);
    mergesort(arr,mid+1,right);
    merge(arr,left,mid,right);
}

void merge_sort(int* arr,int len)
{
    mergesort(int,0,n-1);
}

时间:nlogn
空间:o(n)
时间低,空间高。

8,基数排序:(对找工作来说,了解思想就足够了)
思想:先按照个位数排序,再按照十位数排序,以此类推,这组数中最大数是几位数,就得排几趟。那么每一趟排序又该怎么排呢?举个例子,也就是说如何按照个位数排序呢?
如下图:在排序之前,要开辟十个桶的空间大小,每个通分别放入个位为0,1,2,3,4,5,6,7,8,9的数字,然后再按桶的顺序,将每个桶中的数字拿出来,先拿0号桶中的,全部拿出来之后,再拿一号桶中的,以此类推。这是一趟排序。
再按此规律排十位,百位。最后一次排序,从桶内拿出来就已经是排好的了!
基数排序
很神奇,这种排序是唯一不需要比较的排序方法!
但这个sort需要的辅助空间却很大:需要十个桶,每个桶都必须开辟这组数个大小。

代码取自本篇博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值