静态查找表
一维数组:顺序查找O(n)、二分查找(先排序)O(logn)
二分查找的经典bug:可能带来数组越界的bug,所以low和high要先/2再相加
整数二分
二分出左半边的边界
//区间[l,r]被划分成[l,mid-1]和[mid,r]时使用
int bsearch_1(int l,int r){
while(l<r){
int mid=l+r+1>>1;
if(check(mid))l=mid;
else r=mid-1;
}
return l;
}
二分出右半边的边界
//区间[l,r]被划分成[l,mid]和[mid+1,r]时使用
int bsearch_2(int l,int r){
while(l<r){
int mid=l+r>>1;
if(check(mid))r=mid;
else l=mid+1;
}
return l;
}
浮点数二分
找出左半边满足条件,右半边不满足条件的边界,保证答案落在区间内部,区间足够小时即认为得出答案。
#include<iostream>
using namespace std;
int main(){
double x;
cin>>x;
double l=0,r=x;
if(r<1)r=1; //对于<1的数来说,它的平方不在l~r的内部
while(r-l>1e-10){ //用精度表示,或者直接i循环
double mid=(l+r)/2;
if(mid*mid>=x)r=mid;
else l=mid;
}
printf("%lf\n",l);
return 0;
}
动态查找表
在查找的同时对表进行修改(插入和删除)e.g. cpu的任务调度
在查找过程中同时插入查找表中不存在的元素,或删除某个存在的数据元素
二叉搜索树BST(Binary Search Tree)
结点带权;左子树的每个结点都比根节点小,右子树的每个结点都比根节点大;递归定义
但给定的序列接近有序时,BST会退化成链表
#include<iostream>
#include<stdarg.h>
#include<string>
#include<queue>
using namespace std;
struct BSTNode{
int data,lev;
BSTNode *lchild,*rchild;
};
typedef BSTNode *BST;
BSTNode *find(const BST &B,int x){
if(B==nullptr)return nullptr;//没找到
else if(B->data<x)return find(B->rchild,x);
else if(B->data>x)return find(B->lchild,x);
else return B;//找到
}
BSTNode *findMin(const BST &T){
if(T==nullptr)return nullptr;
else if(T->lchild==nullptr)return T;
else return findMin(T->lchild);
}
BSTNode *findMax(const BST &B){
if(T==nullptr)return nullptr;
else if(T->rchild==nullptr)return T;
else return findMax(T->rchild);
}
BSTNode *insert(BST &B,int x){
if(B==nullptr){
B=new BSTNode();
B->data=x;
B->rchild=B->lchild=nullptr;
}else if(B->data>x)return insert(B->lchild,x);
else if(B->data<x)return insert(B->rchild,x);
return B;//返回该结点
}
BSTNode *remove(const BST &B,int x){
//没有左子或右子,把子往上顶
//既有左子还有右子 从左子挑一个最大的或右子挑一个最小的顶上
//这个天选之点,要用它的左子或右子顶替它原本的位置
if(B=nullptr)return B;
else if(B->data<x){
remove(B->rchild,x);
}else if(B->data>x){
remove(B->lchild,x);
}else{//找到了
if(B->lchild!=nullptr&&B->rchild!=nullptr){
//从右子树找最小结点
BSTNode *node=findMin(B->rchild);
B->data=node->data;
remove(B->rchild,node->data);
//或从左子树找最大结点
// BSTNode *node=findMax(B->lchild);
// B->data=node->data;
// remove(B->lchild,node->data);
}else{//要删的结点只有一个子树
BSTNode *tmp=B;
if(B->lchild==nullptr)B=B->rchild;
else B=B->lchild;
delete tmp;
}
}
}
void pretraverse(BST &T,int level){
if(T==nullptr)return;
fer(i,0,level*4)cout<<" ";
cout<<T->data<<endl;
if(T->lchild!=nullptr&&T->rchild!=nullptr){
pretraverse(T->lchild,level+1);
pretraverse(T->rchild,level+1);
}else if(T->lchild==nullptr&&T->rchild!=nullptr){
fer(i,0,(level+1)*4)cout<<" ";
cout<<"#"<<endl;
pretraverse(T->rchild,level+1);
}else if(T->rchild==nullptr&&T->lchild!=nullptr){
pretraverse(T->lchild,level+1);
fer(i,0,(level+1)*4)cout<<" ";
cout<<"#"<<endl;
}
}
void CalcLevel(BST &T){ //计算层次
queue<BSTNode*> q;
q.push(T);
T->lev=0;
while(!q.empty()){
BSTNode *node=q.front();
q.pop();
if(node->lchild!=nullptr){
node->lchild.lev=node.lev+1;
q.push(node->lchild);
}
if(node->rchild!=nullptr){
node->rchild.lev=node.lev+1;
q.push(node->rchild);
}
}
}
int main(){
int n,t;
cin>>n;
BST T=nullptr;
while(n--){
cin>>t;
insert(T,t);
}
pretraverse(T);
return 0;
}
平衡二叉树 AVL树
平衡因子Balance Factor BF=hl-hr
AVL树的每个结点的|平衡因子|<=1
最小不平衡子树:对它进行调整使之平衡
从新插入的结点出发往上走找到最小不平衡子树T
平衡因子的计算
int callr(const BST &B){
if(B==nullptr)return 0;
else {
if(B->lchild!=nullptr)B->ldepth=callr(B->lchild)+1;
else B->ldepth=0;
if(B->rchild!=nullptr)B->rdepth=callr(B->rchild)+1;
else B->rdepth=0;
}
return max(B->ldepth,B->rdepth);
}
void calbf(const BST &B){
if(B==nullptr)return;
else if(B->rchild==nullptr&&B->lchild==nullptr)B->bf=0;
else{
B->bf=B->ldepth-B->rdepth;
calbf(B->lchild);
calbf(B->rchild);
}
}
int main(){
int n;
cin>>n;
BST T=nullptr;
while(n--){
int tmp;
cin>>tmp;
insert(T,tmp);
}
callr(T);
calbf(T);
pretraverse(T,0);
return 0;
}
销售排行榜
输入格式
输入包括多行数据(行数小于100000),每行数据包括4个信息,分别是商品名称、销售数量、单价、成交日期
商品名称由小写字母组成,且不超过100个字符,销售数量和单价都是正整数,且小于10000
输出格式
输出包括多行数据,将所有在输入中出现的商品按销售数量降序排列,每行数据包括3个信息,分别是商品名称、销售数量、销售额,如果两种商品销售数量一样,则按商品的字母顺序升序排列
输入样例 复制
apple 1 20 2014-4-2
basketball 1 20 2014-4-2
computer 1 20 2014-4-2
shoe 1 20 2014-4-2
tv 1 20 2014-4-2
apple 1 18 2014-4-3
输出样例 复制
apple 2 38
basketball 1 20
computer 1 20
shoe 1 20
tv 1 20
struct node{
int num,sum;
};
bool cmp(const pair<string,node> &a,const pair<string,node> &b){
if(a.second.num==b.second.num){
return a.first<b.first;
}else return a.second.num>b.second.num;
}
int main(){
//freopen("answer/1.txt","r",stdin);
map<string,node> mp;
string a,date;
int c,p;
while(cin>>a>>c>>p>>date){
// if(a=="0")break;
node tmp;
tmp.num=c;tmp.sum=c*p;
if(mp.find(a)==mp.end()){
mp.insert(pair<string,node>(a,tmp));
}else{
mp[a].sum+=tmp.sum;
mp[a].num+=tmp.num;
}
}
vector<pair<string,node> > ans(mp.begin(),mp.end());
sort(ans.begin(),ans.end(),cmp);
for(vector<pair<string,node> >::iterator it=ans.begin();it!=ans.end();it++){
cout<<it->first<<" "<<it->second.num<<" "<<it->second.sum<<endl;
}
return 0;
}
哈希表
线性探测法解决冲突
struct dnw{
string s;
bool used;
}fna[10];
int main(){
int n;
cin>>n;
while(n--){
string snow;
cin>>snow;
int sum=0;
int len=snow.size();
sum=(snow[len-4]-'0')+(snow[len-3]-'0')+(snow[len-2]-'0')+snow[len-1]-'0';
sum%=10;
if(fna[sum].used==0){
fna[sum].used=1;
fna[sum].s=snow;
}else{
int i=1;
int flag=0;
while(sum-i>=0&&sum+i<=9){
if(fna[sum+i].used==0){
fna[sum+i].used=1;
fna[sum+i].s=snow;
flag=1;
break;
}
if(fna[sum-i].used==0){
fna[sum-i].used=1;
fna[sum-i].s=snow;
flag=1;
break;
}
i++;
}
while(sum-i<0&&flag==0){
if(sum+i<=9&&fna[sum+i].used==0){
fna[sum+i].used=1;
fna[sum+i].s=snow;
flag=1;
break;
}
i++;
}
while(sum+i>9&&flag==0){
if(fna[sum-i].used==0&&sum-i>=0){
fna[sum-i].used=1;
fna[sum-i].s=snow;
flag=1;
break;
}
i++;
}
}
}
fer(i,0,10){
if(fna[i].used==0)cout<<"#"<<endl;
else cout<<fna[i].s<<endl;
}
return 0;
}