左神算法课程基础笔记-第二章-高级排序

本文介绍了三种常用的排序算法:归并排序,通过分治策略将数组分为两半,再进行合并;快速排序,使用随机选取的基准值进行分区,递归处理小于和大于基准的子数组;以及桶排序,通过构建堆并调整堆结构进行排序。这些算法在不同的场景下有各自的效率优势。
摘要由CSDN通过智能技术生成

1.归并排序

 1.找到这个待排序数组的中点
 2.两个子排序 left到mid  mid+1到right
 3.然后就是merge过程,需要重新开辟一个新的数组去 helparray
 4.时间复杂度O*(N*LogN)

void merge(vector<int> s, int L, int M, int R) {
    int helparray[R - L + 1];
    int p1 = L; //双指针向右遍历
    int p2 = M + 1;
    int i = 0;
    while (p1 <= M && p2 <= R) {
        if (s[p1] <= s[p2])  //将子序列赋值到新开辟的数组
        {
            helparray[i++] = s[p1++];
        } else {
            helparray[i++] = s[p2++];
        }
        //处理两个子序列剩下的元素
        while (p1 <= M) {
            helparray[i++] = s[p1++];
        }
        while (p2 <= R) {
            helparray[i++] = s[p2++];
        }
        //将help排序过的元素返回原数组
        for (int j = 0; j < sizeof(s) / sizeof(int); ++j) {
            s[L + i] = helparray[i];
        }
    };

}

void process(vector<int> s, int L, int R) {
    //左右边界判断
    if (L == R) {
        return;
    }
    int mid = L + ((R - L) >> 1);//找到中点位置
    process(s, L, mid);//子排序分割
    process(s, mid + 1, R);//子排序分割
    merge(s, L, mid, R); //归并过程
}

2.快速排序

 1.每次整行递归处理,每轮排序都会有一个数在最终的位置
 2.[i]<num 与小于区域的后一个位置交换 小于区右扩i++
 3.[i]=num 原地不动 i++
 4.[i]>num 与大于区域的前一个位置交换,大于区左扩 i不变  // leetcode 荷兰国旗问题可以用这个解决

void swap(vector<int> s,int i,int j)
{
if(i!=j)
{
int eor=s[i]^s[j];
s[i]=eor^s[i];
s[j]=eor^s[j];
}
}
//对区域进行划分
void partition(vec &s, int L, int R) {
    //定义两个区的边界两个指针
    arr[0] = L - 1;
    arr[1] = R;//大于区的左边界//10
    while (L < arr[1])//当i指针与右边界相撞 循环结束
    {
        if (s[L] < s[R]) {//
            swap(s, ++arr[0], L++);//S[R]作为标准值 所有值和他比较
        } else if (s[L] == s[R]) {
            L++;
        } else if (s[L] > s[R]) {
            swap(s, L, --arr[1]);
        }
    }
    swap(s, arr[1], R);
    //将基准元素与大于区域的第一位置交换//返回第一个元素代表当前基准值pivot的第一个相同数字下标,第二个代表最后一个相同数字下标
}
void quickSort(vec &s, int L, int R) {
    if (L < R) {
        int x = (rand() % (R - L + 1));
        swap(s, x, R); //将随机产生的基准值与最后一个位置的元素进行交换  产生在A-B范围内的随机数只需要rand()%x
        partition(s, L, R);//返回两个元素数组 第一个元素代表当前基准值pivot的第一个相同数字下标,第二个代表最后一个相同数字下标
        quickSort(s, L, arr[0] - 1);//处理小于区
        quickSort(s, arr[1] + 1, R);//处理小于区
    }
}

3.桶排序

1:我们要进行堆的构造,将一个数组中的元素按照层次遍历的顺序插入到二叉树中
2:规定一个heapsize来定义堆的大小,如果出堆一个元素就heapsize减一 逻辑意义上的从空间删除
3:定义两个方法 一个heapInsert堆插一个heapify堆化
void heapInsert(vector<int> &vc,int index) //插入节点
{
//二叉树的知识  父亲结点:(i-1)/2 左孩子:2*i 右孩子:2*i+1
while(vc[index]>vc[(index-1)/2])
{
swap(vc,index,(index-1)/2);
index=(index-1)/2;
}
}
void heapify(vector<int> &vc, int index, int heapsize) //这个方法可以将一个数组变成一个大根堆
{
    int left = 2 * index + 1;//右孩子
    //判断是否还有孩子
    while (left < heapsize) {
        //得出两个孩子的大小比较
        int max = left;
        if ((left + 1 < heapsize) && (vc[left] < vc[left + 1]))  //右孩子在范围内
        {
            max = left + 1;
        }
        max = vc[max] > vc[index] ? max : index;
        if (max == index) {
            break;
        }
        swap(vc, max, index);
        index = max;//对一层树操作
    }

}
void heapsort(vector<int> &vc)//将一个数组先变成大根堆,在将他输出
{
    if (vc.size()<2)
    {
        return;
    }
    for (int i = 0; i <vc.size() ; ++i) //大根堆的形成
    {
        heapInsert(vc,i);
    }
    cout<<"大根堆的形成"<<endl;
    for (int i = 0; i < vc.size(); ++i)
    {
        cout<<vc[i]<<endl;//输出元素
    }
    int heapsize=vc.size();
    swap(vc,0, heapsize-1);//弹出顶端元素
    while (heapsize>0)
    {
        heapify(vc,0,heapsize);
        swap(vc,0,--heapsize);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值