数据结构算法——目录
一. 二叉树
1. 根据一个字符串建立二叉树
提交网址
读入输入的字符串,建立一颗以指针方式存储的二叉树,以#表示空树。
abc##de#g##f###
#include<iostream>
#include<string>
using namespace std;
string s;
struct node{
char c;
node *l,*r;
node(char c):c(c){}
};
node* build(int& pos) //pos不能回溯,需为引用类型
{
char c = s[pos];
pos++;
if(c != '#'){
node *p = new node(c);
p->l = build(pos);
p->r = build(pos);
return p;
}
else
return NULL;
}
void inOrder(node *p)
{
if(p == NULL)
return;
inOrder(p->l);
cout << p->c;
inOrder(p->r);
}
int main()
{
int pos = 0;
while(cin >> s){
node *root = build(pos);
inOrder(root);
cout << endl;
}
return 0;
}
2. 根据两个字符串建立二叉树
也就是给定前序中序,来确定后序
提交网址
#include<iostream>
#include<string>
using namespace std;
struct node{
char c;
node *l,*r;
node(char c):c(c){}
};
node* make(string pre,string in)
{
if(pre.size()>0 && in.size()>0){
char c = pre[0];
node *p = new node(c);
int i = in.find(c);
p->l = make(pre. substr(1,i), in.substr(0,i));
p->r = make(pre.substr(i+1), in.substr(i+1));
return p;
}
return NULL;
}
void pos(node* root)
{
if(root){
pos(root->l);
pos(root->r);
cout << root->c;
}
}
int main()
{
string pre,in;
while(cin >> pre >> in){
node* root = make(pre,in);
pos(root);
cout << endl;
}
return 0;
}
二. 二叉排序树
1. 二叉排序树的构造与查找
#include<iostream>
using namespace std;
struct node{
int value;
node *l,*r;
node(int v):value(v),l(NULL),r(NULL){} //刚开始忘记了初始化为NULL
};
void insert(node* &root,int v)
{
if(root == NULL){
root = new node(v);
}
else{
if(v > root->value)
insert(root->r,v);
else
insert(root->l,v);
}
}
void pre(node* p,int v,int father) //该函数也可以写到insert里
{
if(p){
if(p->value == v){
cout << father << endl;
return;
}
pre(p->l,v,p->value);
pre(p->r,v,p->value);
}
}
int main()
{
int n,v;
while(cin >> n)
{
node *root = NULL;
for(int i=0;i<n;i++){
cin >> v;
//此处最好用递归,如果用while向下寻找有些麻烦
insert(root,v);
pre(root,v,-1); //根结点指针、待查找的值、父亲值
}
}
}
三. 优先队列
1. 优先队列的基本使用
题目链接
题很水,只需知道优先队列应用于求解顺序问题,优先级高的位于队列最前。
还有一个要注意的是:重载运算符一定要加const!!而且要写在括号外面!!否则会像没定义比较函数一样报错,原因可能是因为非const类型对象无法在const对象上使用。
#include<iostream>
#include<queue>
#include<string>
using namespace std;
struct complex{
int real,ima;
complex(int r,int i):real(r),ima(i){}
bool operator < (complex o) const{ //重载运算符,注意const的使用及其位置
return real*real+ima*ima < o.real*o.real+o.ima*o.ima;
}
};
int main()
{
int n;
while(cin >> n){
priority_queue<complex> q;
while(n--){
string s;
cin >> s;
getchar();
if(s == "Pop"){
if(q.empty()){
cout << "empty" << endl;
}
else{
complex t = q.top();
q.pop();
cout << t.real<< "+i" << t.ima << endl;
cout << "SIZE = " << q.size() << endl;
}
}
else{
int r,i;
char c;
cin >> r >> c >> c >> i;
q.push(complex(r,i));
cout << "SIZE = " << q.size() << endl;
}
}
}
}
2. 哈夫曼树
n个带有权值的结点构成的哈夫曼树可能不唯一,所以有关哈夫曼树的机试题往往考察的是求解最小带权路径长度和。使用优先队列,可以高效的求出集合中权值最小的两个元素,此时需要的是优先级最小的元素。
求哈夫曼
权值
搬水果
#include<iostream>
#include<queue>
using namespace std;
int main()
{
int n,t;
int a[1002];
while(cin >> n){
priority_queue<int,vector<int>,greater<int> > q;
//优先队列默认less<T>,即递减。若要改成递增,则需要将三个参数都给出
//三个参数分别为:存储对象类型,存储元素的底层容器,compare函数对象
for(int i=0;i<n;i++){
cin >> t;
q.push(t);
}
int res=0;
while(q.size()>1){ //取出两个再放进去一个
int t1 = q.top();
q.pop();
int t2 = q.top();
q.pop();
q.push(t1 + t2);
res += t1 + t2;
}
cout << res << endl;
}
}
四. 散列表
1. 散列表的基本使用
魔咒词典
对于双向映射,当然可以用两个map分别存储key和value。
但如果任何key均不会等于value的情况下,可以直接存在一个map中。即:
mp[key] = value;
mp[value] = key;
2. 子串计算
题目链接
只需想到遍历子串的方法,在哈希表上加一即可。
for(int i=0;i<s.length();i++){
for(int j=i;j<s.length();j++){
string sub = s.substr(i,j-i+1);
mp[sub]++;
}
}
3. 结合vector
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int n,m;
while(cin >> n >> m){
vector<int> v;
int hash[300] = {0};
for(int i=0;i<n;i++){
cin >> m;
hash[m]++;
v.push_back(m);
}
vector<int>::iterator it;
for(it=v.begin();it!=v.end();it++){
int res = hash[*it]-1;
if(res == 0)
cout << "BeiJu" << endl;
else
cout << res << endl;
}
}
}