常见的数据结构
常用数据结构 · 数组bai(静态数组、动态数组)、线性表、链表(单向链表、双向链表、循环链表)、队列、栈、树(二叉树、查找树、平衡树、线索树、线索树、堆)、图等的定义、存储和操作 · Hash(存储地址计算,冲突处理)
排序算法
https://www.cnblogs.com/flyingdreams/p/11161157.html
快排
#include<iostream>
using namespace std;
const int N=100003;
int a[N];
int n;
void quicksort(int l,int r){
if(l>=r) return;
int x=a[l+r>>1],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]);
}
quicksort(l,j);
quicksort(j+1,r);
}
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
quicksort(0,n-1);
for(int i=0;i<n;i++) cout<<a[i]<<' ';
return 0;
}
//10
//49 59 88 37 98 97 68 54 31 3
快排最坏时间复杂度
最好的情况:每次选的pivot几乎能把数据均分成两半,这样递归树的深度就是logN,这样快排的时间复杂度为O(NlogN)
最坏的情况:每次找的pivot将数组分成两部分,其中有一部分是空,这样递归树就变成了一棵倾斜的树。树的深度为n-1,这样时间复杂度就变成了O(N^2).
一般当数据有序或者局部有序的时候会出现这种坏的情况,比如数组正序或者逆序,(数字完全相同的时候也是有序的特殊情况)。
解决方法:
选pivot的时候可以随机选,而不是每次选第一个或者最后一个
对子数组进行快排序的时候可以先扫描一遍,如果子数组有序就不用再快排了。
堆排
#include<iostream>
using namespace std;
const int N=100003;
int a[N],index;
void up(int k){
while(k){
if(a[k/2]>a[k]) swap(a[k/2],a[k]);
else break;
k/=2;
}
}
void down(int k){
int t;
while(k*2<index){
t=k*2;
if(t+1<index&&a[t+1]<a[t]) t++;
if(a[k]>a[t])
swap(a[k],a[t]);
else break;
k=t;
}
}
void push(int k){
a[index]=k;
up(index);
index++;
}
void pop(){
swap(a[0],a[index-1]);
index--;
down(0);
}
int top(){
return a[0];
}
int main(){
int n,m;
cin>>n>>m;
for(int i=0;i<n;i++){
int x;
cin>>x;
push(x);
}
while(m--){
cout<<top()<<' ';
pop();
}
return 0;
}
归排
#include<iostream>
using namespace std;
const int N=100003;
int a[N],t[N];
void merge(int l,int r){
if(l>=r) return;
int m=l+r>>1;
merge(l,m);
if(m+1<=r) merge(m+1,r);
int i=l,j=m+1,k=0;
while(i<=m&&j<=r){
if(a[i]<=a[j]) t[k++]=a[i++];
else t[k++]=a[j++];
}
while(i<=m) t[k++]=a[i++];
while(j<=r) t[k++]=a[j++];
for(int i=l,k=0;i<=r;i++,k++) a[i]=t[k];
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
merge(0,n-1);
for(int i=0;i<n;i++) cout<<a[i]<<' ';
return 0;
}
算法的稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。
海量数据取topK,用大顶堆还是小顶堆,怎么执行
https://www.pianshen.com/article/8760641815/
还有没有其他方法?
快排partion()返回到K。分治法求第k大的数。