c++数据结构:查找

静态查找表

一维数组:顺序查找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;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值