大二博客总结第四周
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大二博客总结第四周相关的知识,希望对你有一定的参考价值。
本周学习内容:
1.了解掌握了二叉树的存储,创建和遍历
2.学会了二叉搜索树(BST),做完了课后习题
3.看懂、学习了简单平衡二叉搜索树——Treap树
4.高精度计算
BST
1.每个元素的键值可以比较大小,将键值存放在BST的结点上
2.键值最大的结点没有右儿子,键值最小的结点没有左儿子
3.最坏的情况下,树的深度为n;最好的情况下,得到的左右子树完全平衡,深度为log2(n).
BST的关键在于运用算法努力使它保持平衡
eg:HDU 3999 “The order of a Tree”
#include <bits/stdc++.h>
using namespace std;
const int N=100005;
int tree[N],l[N],r[N],a[N];
int root,f,m; //root(根)的值为0,以tree[0]为根结点
// f的作用是去记录每个值出现的顺序,m是去控制遍历输出的顺序
void buildtree(int root,int x)
{
if(x<=tree[root])
{
if(l[root]==-1)
l[root]=f; //l[n],r[n]存放的是tree[n]的下标
else
buildtree(l[root],x); //递归向下,存放左儿子
}
else
{
if(r[root]==-1)
r[root]=f;
else
buildtree(r[root],x); //递归向下,存放右儿子
}
}
void order(int root) //将建的树的值进行存储,递归赋给a[N]
{
a[m++]=tree[root];
if(l[root]!=-1)
order(l[root]);
if(r[root]!=-1)
order(r[root]);
}
int main()
{
int n;
while(cin>>n)
{
memset(l,-1,sizeof(l)); //都初始化为-1,方便之后的输出
memset(r,-1,sizeof(r));
root=-1;f=0; //根的值+1后,就没变过
for(int i=0;i<n;i++)
{
int x;
cin>>x;
if(root==-1)
tree[++root]=x; //作为根节点
else
{
tree[++f]=x;
buildtree(root,x); //tree[0]为中心建树
}
}
m=0;
order(root);
for(int i=0;i<m;i++)
cout<<a[i]<<" ";
cout<<endl;
}
}
Treap 树
1.treap树的插入和调整
优先级决定了元素的位置,优先级最高的为树根;而键值决定了元素作为左孩子或是右孩子。优先级高的利用左旋、右旋上升调整位置。
2.treap树的删除:若结点是叶子结点,则直接删除;若结点有子节点,那么找到优先级最大的子节点,向相反方向旋转,调整为叶子结点后删除。
(treap树的代码有点麻烦,有时对应STL容器解题会方便很多)
eg:给出和尚们打架的顺序(P75)页
(灵活使用迭代器,map容器可根据键来进行升序排列)
#include <bits/stdc++.h>
using namespace std;
map<int,int>mp;
int main()
{
int n;
while(cin>>n)
{
mp.clear();
mp[1e9]=1;
while(n--)
{
int id,g;
cin>>id>>g;
mp[g]=id;
int tmp;
map<int,int>::iterator it=mp.find(g);
//用find函数查找到键所在的下标
if(it==mp.begin())
tmp=(++it)->second;
else
{
map<int,int>::iterator it2=it;
it2--;it++;
if((g-it2->first)<=(it->first-g))
tmp=it2->second;
else
tmp=it->second;
}
cout<<id<<" "<<tmp<<endl;
}
}
return 0;
}
而Treap树的代码五由部分构成:
1.定义结点struct Node。2.旋转rorate()。3.插入insert()。4.找第k大的数kth()。5.查询某个数find().
第四、五部分是名次数的两个功能。
(代码就先略了,这部分我还要好好学,理解不深,后面补)
高精度计算
书本上用JAVA实现,主要运用两个系统已经编写好的类。而c,c++中处理大数,需要用数组模拟,然后按位处理进位,借位。
万进制解决大数问题:
1.先将大的数字从右到左进行分配.
eg:12346789
sum[0]=6789,sum[1]=1234
2.进位取余。eg:12346789*15
sum[0]*15=101835;beyond=101835/10000=10;
sum[0]=sum[0]%10000=1835
sum[1]=1234*15+beyond(10)=18520
beyond=18520/10000=1;
sum[1]=8520
sum[2]=sum[2]+beyond=1
结果为:185201835
3.除了最高位若不满足4位,则在左边补0.
万进制求解n的阶乘(n>=1&&n<=10000)
#include <bits/stdc++.h>
using namespace std;
int sum[10005];
int main()
{
int beyond,last,n;
while(cin>>n)
{
memset(sum,0,sizeof(sum));
sum[0]=1;
last=0;
//记录每次乘上一个i,四位一组,组成的个数
for(int i=1;i<=n;i++)
{
beyond=0;
for(int j=0;j<=last;j++) // 内循环为万进制操作
{
sum[j]=sum[j]*i+beyond;
beyond=sum[j]/10000;
sum[j]%=10000;
}
if(beyond>0)
{
last++;
sum[last]=beyond;
}
}
cout<<sum[last];
for(int i=last-1;i>=0;i--)
{
cout<<setw(4)<<setfill('0')<<sum[i];
}
cout<<endl;
}
return 0;
}
以上是关于大二博客总结第四周的主要内容,如果未能解决你的问题,请参考以下文章
2017-2018-1 20155305 《信息安全系统设计基础》第四周学习总结(课堂提交作业未来得及提交码云链接myod补充博客)