复试上机指南之数据结构二

11 篇文章 0 订阅
11 篇文章 0 订阅

二叉树

二叉树的前、中、后序、层次遍历

struct tree{
	char c;
	tree* leftnode;
	tree* rightnode;
}; 
//先序遍历 
void preorder(tree* root){
	if(root==NULL){
		return;
	}
	cout<<root->c;
	preorder(root->leftnode);
	preorder(root->rightnode);
	return;
}
//中序遍历 
void inorder(tree* root){
	if(root==NULL){
		return;
	}
	preorder(root->leftnode);
	cout<<root->c;
	preorder(root->rightnode);
	return;
}
//后序遍历 
void postorder(tree* root){
	if(root==NULL){
		return;
	}
	preorder(root->leftnode);
	preorder(root->rightnode);
	cout<<root->c;
	return;
}
//层序遍历
void levelorder(tree* root){
	queue<tree*>myQueue;
	if(root!=NULL){
		myQueue.push(root);
	}
	while(!myQueue.empty()){
		tree* current = myQueue.front();
		myQueue.pop();
		cout<<current.c;
		if(current->leftchild != NULL){
			myQueue.push(current->leftnode);
		}
		if(current->rightchild != NULL){
			myQueue.push(current->rightnode);
		}
	}
}

二叉树的创建

按照前序、中序、后序给出的字符串按照给出的顺序创建(以下代码)即可,若没有给出顺序,只是一个字符串,按照层次遍历的顺序创建字符串。

//给一个字符串,创建一个二叉树
tree *build(int& position,string str){
	char a = str[position++];
	if(a=='#'){
		return NULL;
	}
	tree* node = new tree;
	node->c = a;
	node->leftnode = NULL;
	node->rightnode = NULL;
	node->leftnode = build(position,str);
	node->rightnode = build(position,str);
	return node;
} 

根据前序、中序或者后序中序确定一个二叉树

struct tree{
	char c;
	tree* leftnode;
	tree* rightnode;
	tree(char a): c(a),leftnode(NULL),rightnode(NULL){}
};
//若是给的后序的话,则char a= s1[s1.size()-1],后面一样; 
tree* build(string s1,string s2){
	if(s1.size()==0){
		return NULL;
	}
	char a=s1[0];
	tree* node=new tree(a);//构造函数
	int position = s2.find(a);
	node->leftnode = build(s1.substr(1,position),s2.substr(0,position));
	node->rightnode = build(s1.substr(position+1),s2.substr(position+1));
	return node;
} 

二叉排序树

构建一个二叉排序树

struct tree{
	int a;
	tree* leftnode;
	tree* rightnode;
	tree(int c): a(c),leftnode(NULL),rightnode(NULL){}
};
//构建二叉排序树
tree* insert(tree* root,int x,int father){
	if(root == NULL){
		root = new tree(x);
		cout<<father<<endl;
	}else if(x<root->a){
		root->leftnode = insert(root->leftnode,x,root->a);//左右子树都是一个二叉排序树,直接调用就行。 
	}else if(x>root->a){
		root->rightnode = insert(root->rightnode,x,root->a);
	}
	return root;
}

优先队列

优先队列,又称为优先级队列、堆。优先队列是一种特殊的队列,除了具有队列的先入先出,队列头出,队列尾入的结构特点,优先队列最重要的就是要实现快速得到队列中优先级最高的元素,因此,优先队列有一定的顺序特点,这是一种弱序,即队列头部的那个元素是优先级最高的,我们往往以元素值的大小作为优先级来讨论,比如说,数值大的优先级高,则优先队列元素会按一定规则的大小顺序排列,从而使得在队列头部的元素始终保持数值最大(优先级最高)的特点。总之,优先队列的目的就是实现将元素入队列,并快速返回队列优先级最高优先级元素

可以理解为大顶堆、小顶堆,在初始化的时候可以指定按照大或小顶堆排序,不指定的话默认是大顶堆,也就是优先级高(数值大)的在最前面。

下面是默认初始化和指定初始化的三种方式:

#include<queue>//头文件和普通队列一样
//大顶堆也就是默认的方式,输入1 2 3 4 5 6,输出6
	int n,a;
	priority_queue<int,vector<int>,less<int> > p; 
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a;
		p.push(a);
	}
	cout<<p.top()<<endl;
//小顶堆的方式,输入1 2 3 4 5 6,输出1
	int n,a;
	priority_queue<int,vector<int>,greater<int> > p; 
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a;
		p.push(a);
	}
	cout<<p.top()<<endl;
//默认方式,输入1 2 3 4 5 6,输出6
	int n,a;
	priority_queue<int> p; 
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a;
		p.push(a);
	}
	cout<<p.top()<<endl;

散列表

在STL中有一个unordered_map即无序映射,其第层是散列表实现的。map是有序映射其底层是红黑树实现的,顾有一定的顺序;在使用的时候两者操作是相同的,可以使用map,但是在遇到要求性能特别高的时候,我们可以将map改为unordered_map。

map小技巧

关于map之前介绍STL的时候写过,这里记录一些使用时的技巧。

在map中常用的有find(),用来查找特定元素,返回值是该元素的迭代器。

  1. 输入N个学生的信息,进行查询,我们最直观想到的时使用结构体,其实这个题没有对信息进一步的操作,所以我们可以使用字符串来解决,将学号看作key,将字符串的信息作为values,查询到key时,直接输出str。
map<string,strng> student;
for(int i=0;i<n;i++){
	string str;
	getline(cin,str);//使用getline是因为它可以接收空格。
	int pos = str.find(' ');//第一个输入的是学号作为key,values是str,即寻找分界点。
	string key = str.substr(0.pos);//学号作为关键字
	student[key] = str;//信息作为映射值。
}
//输出
for(int i=0;i<m;i++){
	string key;
	cin>>key;
	string answer = student[key];
	if(answer ==  ' '){
		answer = "No answer!";
	}
	cout<<answer<<endl;
}
  1. 在输入key、values时我们往往通过key寻找values,但是如果题目中要求既可以通过key寻找values,又可以通过values输出key,我们当然可以通过建立两个map来实现,但是操作有些繁琐,其实我们可以直接建立双向映射同时放在通一个映射中,具体看代码。
map<string,string>m;
string s;
int pos = s.find(']');//分界点
string key = s.substr(0,pos+1);//key
string value = s.substr(pos+2);//key空格之后的都是values.
m[key] = value;
m[value] = key;

//查找输出
strig ke;
getline(cin,ke);
string answer = m[ke];
if(answer == ""){
	answer = "what?";
}else if(answer[0] == '['){
	answer=answer.substr(1,answer.size()-2);//删除字符中两侧的[]。
}
cout<<answer<<endl;
  1. 给一个以0、1组成的字符串,返回每个子串出现的次数。
string str;
cin>>str;
map<string,int>m;
for(int i=0;i<=str.size();i++){
	for(int j=0;j<i;j++){
		string key = str.substr(j,i-j);
		m[key]++;
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

li_jeremy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值