左神算法学习(个人笔记)C++版3.快排,堆,基数(桶)排序、多种算法总结

快速排序代码 

(  考研期间学的快排代码,跟左神不太一样,但是好记,就用这个了)

#include<iostream>
using namespace std;



void quickSort(int arr[],int left,int right){
    
    if(left<right){
    int i=left,j=right;
    int pivot=arr[left];

  

    while(i<j){
        while(i<j&&arr[j]>=pivot)j--;//从后往前,碰到第一个比pivot小的数再交换
        arr[i]=arr[j];
        while(i<j&&arr[i]<=pivot)i++;//从前,碰到第一个比pivot大的数再交换
        arr[j]=arr[i];

    }

    arr[i]=pivot;//此时arr[i]的位置就是pivot应该在的位置
    quickSort(arr,left,i);
    quickSort(arr,i+1,right);
}
}

int main(){

int arr[100];
int n;
cin>>n;



for(int i=0;i<n;i++){
    cin>>arr[i];
}
quickSort(arr,0,n-1);
for(int i=0;i<n;i++){
    cout<<arr[i]<<" ";
}

}


堆排序代码

#include <iostream>
#include <vector>
using namespace std;

// 向上调整,但是O(nlogn)
void heapInsert(vector<int> &arr, int index)
{
    while (arr[index] > arr[(index - 1) / 2])
    {
        swap(arr[index], arr[(index - 1) / 2]);
        index = (index - 1) / 2;
    }
}

// 向下调整,
void adjust(vector<int> &arr, int len, int index)
{
    int left = 2 * index + 1;  // index的左子节点
    int right = 2 * index + 2; // index的右子节点
    int maxIdx = 0;
    while (left < len)
    {

        // 两个孩子比大小,maxIDx赋给大孩子
        maxIdx = (right < len && arr[left] < arr[right]) ? right : left;
        // 大孩子和父比大小,maxIDx赋给大的
        maxIdx = (arr[maxIdx] > arr[index]) ? maxIdx : index;

        if (maxIdx != index)
        {
            swap(arr[maxIdx], arr[index]);
            index = maxIdx;
            left = 2 * index + 1;  // index的左子节点
            right = 2 * index + 2; // index的右子节点
        }
        else
        {
            break;
        }
    }
}

// 堆排序
void heapSort(vector<int> &arr, int size)
{

    // ①调整为大根堆
    // for(int i=0;i<size;i++)
    //     heapInsert(arr,i);
    // ②调整为大根堆
    for (int i = size / 2; i >= 0; i--)
    {
        adjust(arr, size, i);
    }

    // 排序输出大根堆
    for (int i = size - 1; i >= 1; i--)
    {
        swap(arr[0], arr[i]); // 将当前最大的放置到数组末尾
        adjust(arr, i, 0);    // 将未完成排序的部分继续进行堆排序
    }
}

int main()
{
    vector<int> arr = {4, 6, 8, 7, 50, 3, 100, 5, 9};
    heapSort(arr, arr.size());
    for (int i = 0; i < arr.size(); i++)
    {
        cout << arr[i] << "  ";
    }
    cout << endl;
    return 0;
}

同时,学会计算建堆的时间复杂度为O(n)

3.堆排序的stl(感觉没什么用,一般都用priority_queue)了


    #include<vector>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    using namespace std;


//默认建堆是大根堆,,,但很奇怪,如果a>b跑不出小根堆,堆有点问题
bool cmp(int a,int b){
    return a<b;
}
     

int main(){
    vector<int> num={4,1,-1,2,-1,2};
    vector<int> res;
    
    make_heap(num.begin(),num.end());//建堆
    
    num.push_back(3);
    push_heap(num.begin(),num.end());//插入数据


     for(int i=0;i<7;i++){
        cout<<num[i]<<" ";
    }
    cout<<endl;
    sort_heap(num.begin(),num.end());//排序输出

    for(int i=0;i<7;i++){
        cout<<num[i]<<" ";
    }

}

4.优先级队列(priority_queue())其实是堆

参考的这个网站:https://www.cnblogs.com/MrLiuZF/p/13454259.html

// 16:08
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
typedef pair<int, int> P;

//用于重写operator函数
struct cmp
{
    bool operator()(P a, P b)
    {
        return a.first > b.first;
    }
};

int main()
{
    priority_queue<int> cost1;                            // 1.默认大根堆,,等同于priority_queue<int,vector<int>,less<int>> cost1;
    priority_queue<int, vector<int>, greater<int>> cost2; // 2.小根堆

    // 3.如果是自定义类,(包括指针,pair,map等等),需要重写重写operator函数

    priority_queue<P, vector<P>, cmp> cost3; // 小根堆
    cost3.push({3, 10});
    cost3.push({11, 10});

    cout << cost3.top().first;

    return 0;
}

4.1 力扣23 合并K个升序链表

优先级队列的定义,默认是大根堆,如果想要小根堆,需要额外定义一个cmp函数,而如果优先级队列里面存的是链表指针这些,cmp比较函数需要用一个struct包装,格式需要额外记一下。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    

    struct cmp{
        bool operator()(ListNode *H1, ListNode *H2){
            return H1->val > H2->val; // 小根堆排序
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode* dummyHead=new ListNode(0);
        ListNode* curr=dummyHead;
        priority_queue<ListNode *,vector<ListNode *>,cmp> stack;
        for(auto node:lists){
            if(node!=NULL){
            stack.push(node);}
        }
        while(!stack.empty()){
            ListNode *nextNode=stack.top();
            stack.pop();
            curr->next=nextNode;
            curr=curr->next;
            if(nextNode->next!=NULL){
                stack.push(nextNode->next);
            }
        }
        return dummyHead->next;

    }
};

同时用了C++的比较器

5.有点累了,桶排序晚点再看

花了挺长时间自己写的桶排序,但感觉有点复杂,等学深了再回头来改进这代码


#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;


//最大位数
int getHighBit(vector<int> &num){
    int highBit=0;
    int max = 0;
    for (int i = 0; i < num.size(); i++)
    { // 找到最大值
        if (max < num[i])
            max = num[i];
    }
    // 根据最高位数确定要循环多少次
    while (max)
    {
        highBit++;
        max /= 10;
    }
    return highBit;
}
// 指定位数是几(比如255835,第三位为8)
int sureBit(int a, int bit)
{
    int res = 0;
    while (bit)
    {
        res = a % 10;
        bit--;
        a /= 10;
    }
    return res;
}

void bucketSort(vector<int> &num)
{
    int len = num.size();
    vector<vector<int>> bucket(10); // 建立十个桶
    int highBit = getHighBit(num);//最高位
    int cur = 0;
    //循环highBit次
    for (int i = 0; i < highBit; i++)
    {

        // 根据位数将数据入桶
        for (int j = 0; j < len; j++)
        {
            cur = sureBit(num[j], i + 1);
            bucket[cur].push_back(num[j]);
        }
        int k3 = len - 1;

        // 出桶(反着出是因为这个vector没法pop_front()!!!!,只能从屁股后面开始弹出了)
        vector<int> n;
        for (int k1 = 9; k1 >= 0; k1--)
        {

            for (int k2 = bucket[k1].size() - 1; k2 >= 0; k2--)
            {
                num[k3] = bucket[k1][k2];
                bucket[k1].pop_back();
                k3--;
            }
        }
    }
}

int main()
{
    vector<int> num = {1, 55, 343, 56, 34, 6, 3434, 3412, 13, 77};
    bucketSort(num);
    for (int i = 0; i < num.size(); i++)
    {
        cout << num[i] << " ";
    }
    return 0;
}

6.各种排序算法总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值