左程云算法课—03课程笔记

目录

一、堆

二、堆排序

三、比较器的使用

四、桶排序

桶排序思想下的排序

一、堆

1、堆结构就是用数组实现的完全二叉树结构

2、完全二叉树中如果每棵子树的最大值都在顶部就是大根堆

3、完全二叉树中如果每棵子树的最小值都在顶部就是小根堆

4、堆结构的heapInsert与heapify操作

5、堆结构的增大和减少

6、优先级队列结构,就是堆结构

heapInsert操作代码:

void heapInsert(int arr[],int index)
{
    while(arr[index]>arr[(index-1)/2])
    {
        swap(arr,index,(index-1)/2);
        index=(index-1)/2;
    }
}

healpInsert操作是寻找根节点是否比当前节点小,若比当前节点小则交换,index继续指向当前节点,直到根节点大于当前节点

heapify操作代码:

void heapify(int arr[],int index)
{
    int left=index*2+1;
    while(left<heapsize)
    {
        int lagster=left+1<heapsize&&arr[left+1]>arr[left]?left+1:left;//若右子节点大于左子节点则返回右子节点,反之,返回左子节点
        lagster=arr[lagster]>arr[index]?lagster:index;
        if(lagster==index) return;
        swap(arr[lagster],arr[index]);
        index=lagster;
        left=index*2+1;
    }
    
}

二、堆排序

堆排序1,先让整个数组都变成大根堆结构,建立堆的过程:

1、从上到下的方法,时间复杂度为O(N*logN)2)从下到上的方法,时间复杂度为O(N)

2、把堆的最大值和堆末尾的值交换,然后减少堆的大小之后,再去调整堆,一直周而复始,时间复杂度为O(N*logN)

3、堆的大小减小成0之后,排序完成

题目链接:排序

class Solution {
public:
int healpsize;
    vector<int> sortArray(vector<int>& nums) {
        healpsize=nums.size();
        int n=nums.size();
        for(int i=nums.size()-1;i>=0;i--)
        {
            heap(nums,i);
        }
    
    swapp(nums,0,--healpsize);
    while(healpsize>1)
    {

        heap(nums,0);
        swapp(nums,0,--healpsize);

    }
    return nums;
    }
    void heap(vector<int>&arr,int index)
{
    int l=index*2+1;
    while(l<healpsize)
    {
        int lagster=l+1<healpsize&&arr[l]<arr[l+1]?l+1:l;
        lagster=arr[lagster]<arr[index]?index:lagster;
        if(index==lagster)
        {
           return;
        }
        swapp(arr,index,lagster);
        index=lagster;
        l=index*2+1;
    }
}
void swapp(vector<int>& arr,int l,int r)
{
    arr[l]=arr[l]^arr[r];
    arr[r]=arr[l]^arr[r];
    arr[l]=arr[l]^arr[r];
    return;
}
void heapInsert(vector<int>& arr,int index)
{
    while(arr[index]>arr[(index-1)/2])
    {
        swapp(arr,index,(index-1)/2);
        index=(index-1)/2;
    }
}
};

简短版:

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        priority_queue<int,vector<int>,greater<int>>big;
        for(int i=0;i<nums.size();i++)
        {
            big.push(nums[i]);
        }
        for(int i=0;i<nums.size();i++)
        {
            nums[i]=big.top();
            big.pop();
        }
        return nums;
    }
};

问题一:

已知一个几乎有序的数组,几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离可以不超过k,并且k相对于数组来说比较小。请选择一个合适的排序算法针对这个数据进行排序。

分析:准备一个小根堆,遍历数组,假设k=6,则先遍历前7个数,0~6放入小根堆,那么小根堆的最小值一定放在0位置上,因为由题意,每个元素移动的距离一定不超过k,所以小根堆的最小值弹出的数字放在0位置上,然后将7位置上的数放入小根堆,小根堆弹出的数字放到1位置,以此类推

int main()
{
    priority_queue<int,vector<int>,greater<int>>small_heap;
    int n,k;
    cin>>n>>k;
    int index=0;int x;
    int arr[100];
    for(int i=0;i<n;i++)
    {
        cin>>arr[i];
    }
    for(;index<=min(n,k);index++)
    {

        small_heap.push(arr[index]);
    }
    int i=0;
    for(;index<n;i++,index++)
    {
        small_heap.push(arr[index]);
        arr[i]=small_heap.top();
        small_heap.pop();
    }
    while(!small_heap.empty())
    {
        arr[i++]=small_heap.top();
        small_heap.pop();
    }
    for(int i=0;i<n;i++)
    {
        cout<<arr[i]<<' ';
    }
    return 0;
}

用c++的优先队列

手写的堆可以改变其中的数字,但是黑盒的堆不支持

有些情境下手写堆更高效

三、比较器的使用

1)比较器的实质就是重载比较运算符

2)比较器可以很好的应用在特殊标准的排序上

3)比较器可以很好的应用在根据特殊标准排序的结构上

在c++中就是重载运算符

四、桶排序

桶排序思想下的排序

1)计数排序

2)基数排序分析:

1)桶排序思想下的排序都是不基于比较的排序

2)时间复杂度为O(N),额外空间负载度O(M)

3)应用范围有限,需要样本的数据状况满足桶的划分

假设有0~9号桶,从左往右根据个位数字依次将数组元素放入桶中,然后把桶中的数字从左往右依次倒出,然后再根据十位数字从左往右放入桶中

代码为:

class Solution {
public:
    vector<int> sortArray(vector<int>& nums) {
        radixSort(nums);
        return nums;
    }
    void radixSort(vector<int>& nums){
        if(nums.size()<2)return;
        radixSort(nums,0,nums.size()-1,maxbits(nums));
    }
    int maxbits(vector<int>& nums){
        int maxx=nums[0];
        for(int i=0;i<nums.size();i++)
        {
            maxx=max(maxx,nums[i]);
        }
        int res=0;
        while(maxx!=0)
        {
            res++;
            maxx/=10;
        }
        return res;
    }
   
    void radixSort(vector<int>& nums,int l,int r,int digit){
        int radix=10;
        int cout[radix];
         memset(cout,0,radix);
        int i=0,j=0;
        int n=r-l+1;
        int bucket[n];
        memset(bucket,0,n);
        for(int d=1;d<=digit;d++)
        {
            
            for(i=l;i<=r;i++)
            {
                j=getDigit(nums[i],d);
                cout[j]++;
            }
            for(i=1;i<radix;i++)
            {
                cout[i]=cout[i]+cout[i-1];
            }
            for(i=r;i>=l;i--)
            {
                j=getDigit(nums[i],d);
                bucket[cout[j]-1]=nums[i];
                cout[j]--;
            }
            for(i=l,j=0;i<=r;i++,j++){
                nums[i]=bucket[j];
            }
        }
    }
    int getDigit(int c,int d)
    {
        return((c/((int)pow(10,d-1)))%10);
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值