1、快速排序精髓
一、先从数列中取出一个数作为基准数 二、分区,将比这个数大的数全放到它的右边,小于或等于它的数全部放到它的右边 三、对左右区间重复步骤(二),直到各区间只有一个数为止
#include<bits/stdc++.h>
using namespace std;
void qsort(int a[],int l,int r){
if(l>=r) return ; ///找完了
int x=a[l+r>>1];///选中间数为基数然后去快排
int i=l-1,j=r+1;///先越界范围处理 因为下面是先--和++
while(i<j){
while(a[++i]<x);//找到第一个比它小的
while(a[--j]>x);///找到第一个比它大的
if(i<j) swap(a[i],a[j]); ///交换
}
qsort(a,l,i);///将找到的大于和小于基数的两边分
qsort(a,i+1,r);
}
int main(){
int a[100];
int n; cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
qsort(a,1,n);
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
return 0;
}
2.归并排序(Merge Sort)(知乎上大佬看到的传送门附上,方便回顾点这里)
该算法是利用分治思想解决问题的一个非常典型的应用,归并排序的基本思路就是先把数组一分为二,然后分别把左右数组排好序,再将排好序的左右两个数组合并成一个新的数组,最后整个数组就是有序的了。
运用递归法实现归并操作的主要步骤:
1.申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列。
2.设定两个指针,最初位置分别为两个已经排序序列的起始位置。
3.比较两个指针所指向的元素,选择较小的元素放入到合并空间,并将指针移动到下一位置。
4.重复步骤3直到某一指针到达序列尾,然后将另一序列剩下的所有元素直接复制到合并序列尾
#include<iostream>
#include<vector>
using namespace std;
void Merge(vector<int>& , int , int , int );
void MergeSort(vector<int>& , int , int );
int main() {
vector<int> test = { 3, 7, 6, 4, 5, 1, 2, 8 };
MergeSort(test,0,test.size()-1);
for (auto x : test)
cout << x << " ";
return 0;
}
void Merge(vector<int>& arr, int left, int mid, int right) {
int i = left;
int j = mid + 1;
int k = 0;
vector<int> temp(right - left + 1);
while (i <= mid && j <= right)
temp[k++] = arr[i] <= arr[j] ? arr[i++] : arr[j++];
while (i <= mid)
temp[k++] = arr[i++];
while (j <= right)
temp[k++] = arr[j++];
for (int m = 0; m < temp.size(); m++)
arr[left + m] = temp[m];
}
void MergeSort(vector<int>& arr,int left, int right) {
if (left >= right) return;
int mid = left + (right - left) / 2;
MergeSort(arr, left, mid);
MergeSort(arr, mid + 1, right);
Merge(arr, left, mid, right);
}
今天是2021/7/3,又去学到一个排序 ,堆排大佬博客传送门点开他啊
堆排序
什么是堆?堆的用处?
堆:完全二叉树 + 满足某种条件(父亲结点比左右儿子小 或 父亲结点比左右儿子大)
堆(heap)有时被称为优先队列(priority queue)。堆和队列有相似地方,在堆底插入元素,在堆顶取出元素,但是堆中元素的排列不是按照到来的先后顺序,而是按照一定的优先顺序排列的
算法分析
以小根堆为例
小根堆:父亲结点比左右儿子小
堆最好能满足一下五个功能
- 插入一个数
- 求集合中的最小值
- 删除最小值
- 删除集合中任意一个数
- 修改集合中任意一个数
STL中的priority_queue可以实现功能1,2,3
而我们如何自己手写一个堆可以实现功能1,2,3,4,5
down()和up()函数代码模版
// 值变化,往下维护
void down(int u) {
int t = u; // t记录最小值的下标
if (2 * u <= size_ && h[2 * u] < h[t]) t = 2 * u; // 左儿子存在,且值比父亲小
if (2 * u + 1 <= size_ && h[2 * u + 1] < h[t]) t = 2 * u + 1; // // 右儿子存在,且值比父亲小
if (t != u) {
swap(h[t], h[u]);
down(t);
}
return;
}
// 值变化,往上维护
void up(int u) {
if (u / 2 > 0 && h[u / 2] > h[u]) {
swap(h[u / 2], h[u]);
up(u / 2);
}
return;
}
C++代码模板
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define fio ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#define mse(a,b) memset(a,b,sizeof a)
#define pb push_back
#define pii pair<int,int>
using namespace std;
const int mod = 1e9 + 7;
const int maxx = 1e6 + 10;
const double eps = 1e-6;
using namespace std;
const ll inf = 0x3f3f3f3f3f3f3f;
const long double PI = 3.14159265358979323846;
//inline ll read(){ ll x=0,f=1; char ch=getchar(); while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); } while (isdigit(ch)) { x=x*10+ch-48; ch=getchar(); } return x*f;}
// ll cc = ((1ll << 62) - 1 + (1ll << 62));
/*struct node {
ll l,r ,lazy,val;
node() :l(),r(),lazy(),val(){}
node(ll a, ll b, ll c,ll d) :l(a),r(b),lazy(c),val(d){}
};*/
int a[maxx],n;
void down(int x){
int t=x;
if(x*2<=n&&a[x*2]<a[t]) t=x*2;
if(x*2+1<=n&&a[1+x*2]<a[t]) t=x*2+1;
if(t!=x){
swap(a[t],a[x]);
down(t);
}
}
void up(int u) {
if (u / 2 > 0 && a[u / 2] > a[u]) {
swap(a[u / 2], a[u]);
up(u / 2);
}
return;
}
int main(){
fio n=100;
for(int i=1;i<=n;i++) a[i]=rand()%1007;
for(int i=n/2;i>=1;i--) down(i);
while(n){
cout<<a[1]<<" ";
a[1]=a[n];
n--;
down(1);
}
return 0;
}