二叉树
二叉树是一类较高级的存储结构,它的定义如下
struct node
{
int value;
node *l,*r;
};
二叉树是树这一种存储结构中最具代表性的一类,树是非线性的数据结构,可以直观的表示出层次关系,对于如目录一类问题的实现作用显著。
二叉树的基本操作
遍历:遍历操作是最基本的二叉树操作,可以在这个的基础上进行插入和删除等其他操作,而在遍历中又分为了三种遍历方式,前序,中序和后序,二叉树的遍历操作都是建立在递归上的,而这三种遍历方式格式也大同小异。
int post[1000];
void preorder(node*root)//前序
{
if(root!=NULL)
post[k++]=root->value;
preorder(root->l);
preorder(root->r);
}
void inorder(node*root)//中序
{
if(root!=NULL)
{
preorder(root->l);
post[k++]=root->value;
preorder(root->r);
}
}
void postorder(node*root)//后序
{
if(root!=NULL)
{
preorder(root->l);
preorder(root->r);
post[k++]=root->value;
}
}
建树:以上三种顺序给出任何一种都不能得到具体的二叉树,必须要两种顺序才能得到目标二叉树。
拿已知前序和中序求后序举例
for(int i=1;i<=n;i++) cin>>pre[i];
for(int j=1;j<=n;j++) cin>>in[j];
void buildtree(int l, int r, int &t, node* &root) { //建树
int flag = -1;
for(int i = l; i <= r; i++) //先序的第一个是根,找到对应的中序的位置
if(in[i] == pre[t]){
flag = i; break;
}
if(flag == -1) return; //结束
root = new node(in[flag]); //新建结点
t++;
if(flag > l) buildtree(l, flag - 1, t, root ->l);
if(flag < r) buildtree(flag + 1, r, t, root ->r);
}
void preorder (node *root){ //求先序序列
if(root != NULL){
post[k++] = root ->value; //输出
preorder (root ->l);
preorder (root ->r);
}
}
可见DFS对于实现二叉树的遍历是非常发方便的。
二叉搜索树
二叉搜索树也叫BST,与二叉树相比,他具有唯一的键值,能够进行比较大小,其中每个节点的左子树的任意键值都小于这个节点的键值,而他的右子树则又都大于这个键值(可以得到键值中最大的一个没有右子树,而键值最小的没有左子树)
但是二叉搜索树的建树过程取决于所给节点的顺序,如果按顺序给出,则建立的二叉搜索数的访问复杂度将会达到O(n),当给出的顺序是每段数的中间值时将会得到平衡的二叉搜索树,也就是对数级别的访问复杂度,因此,二叉搜索树执行的每个操作都与BST本身的形态有关,因此引入一个新的二叉树,Treap树,二叉搜索平衡树。
二叉搜索平衡树在键值的基础上又增加了优先级的权值,虽然这样也只能随机生成二叉树,但是可以进行动态调整,逐步编程二叉平衡树。这里就要引入一种操作方法,旋转。
void rotate(Node* &o,int d)// d=0左旋,d=1右旋
{
Node * k=o->son[d^1];//d^1效果与d-1等价,但是更快
o->son[d^1]=k->son[d];
k->son[d]=o;
o=k;// 返回新的根
}
这个操作可以让k往上走,代替父节点,最终得到一个新的Treap树。