代码来源:晴神《算法笔记》!!
二叉树的存储与基本操作
- 定义
struct node{
typename data;
node* lchild;
node* rchild;
};
- 新建结点
node* newnode(int v){
node* Node = new node;
Node->data = v;
Node->lchild = Node->rchild = NULL;
return Node;
}
- 二叉树的修改
void search(node* root, int x, int newdata){
if(root == NULL){
return;
}
if(root->data == x){
root->data = newdata;
}
search(root->lchild, x, newdata);
search(root->rchild, x, newdata);
}
- 二叉树结点的插入
//注意根结点指针root要使用引用
//如果要修改二叉树的结构,那么就要加引用
//如果只是对结点的内容做修改或者遍历树,那么不需要加引用
void insert(node* &root, int x){
if(root == NULL){
root = newnode(x);
return;
}
if(应该插在左子树){
insert(root->lchild, x)
}
else{
insert(root->rchild, x);
}
}
- 二叉树的创建
node* create(int data[], int n){
node* root = NULL; //容易漏掉
for(int i = 0; i < n; i++){
insert(root, data[i]);
}
return root;
}
- 完全二叉树的存储结构
完全二叉树如果按照层次遍历的顺序编号,若根结点编号为1,某结点编号为x,那么其左孩子编号为2x,右孩子编号为2x+1;若根结点编号为0,那么x结点的左孩子编号为2x+1,右孩子编号为2x+2。
判断某个结点是叶结点的标志为:左孩子2x>总结点个数n;判断某个结点是空结点的标志为:x>总结点个数n。
二叉树的遍历
先序遍历
void preorder(node* root){
if(root == NULL){
return;
}
printf("%d",root->data);
preorder(root->lchild);
preorder(root->rchild);
}
中序遍历
void inorder(node* root){
if(root == NULL){
return;
}
inorder(root->lchild);
printf("%d",root->data);
inorder(root->rchild);
}
后序遍历
void postorder(node* root){
if(root == NULL){
return;
}
postorder(root->lchild);
postorder(root->rchild);
printf("%d",root->data);
}
层次遍历
//如果需要记录层次
struct node{
int data;
node* lchild;
node* rchild;
int layer;
};
void layerorder(node* root){
queue<node*> q; //注意这里存放的是地址
root->layer = 1;
q.push(root);
while(!q.empty()){
node* now = q.front();
q.pop();
printf("%d",now->data);
if(now->lchild != NULL){
now->lchild->layer = now->layer + 1;
q.push(now->lchild);
}
if(now->rchild != NULL){
now->rchild->layer = now->layer + 1;
q.push(now->rchild);
}
}
}
已知二叉树的先序遍历、后序遍历、层次遍历之一和中序遍历,可以构造出唯一的二叉树。下面以先序遍历和中序遍历为例:
利用先序遍历和中序遍历构造二叉树
node* create(int prel, int prer, int inl, int inr){
if(prel > prer) return NULL;
node* root = new node;
root->data = pre[prel];
int k;
for(k = inl; k <= inr; k++){
if(in[k] == pre[prel]){
break;
}
}
int numleft = k - inl;
root->lchild = create(prel+1, prel+numleft, inl, k-1);
root->rchild = create(prel+numleft+1, prer, k+1, inr);
return root;
}
二叉树的静态实现
//定义
struct node{
typename data;
int lchild;
int rchild;
}Node[maxn];
//新建结点
int index = 0;
int newnode(int v){
Node[index].data = v;
Node[index].lchild = -1;
Node[index].rchild = -1;
return index++;
}
//修改
void search(int root, int x, int newdata){
if(root == -1)
return;
if(Node[root].data == x){
Node[root].data = newdata; //没有return
}
search(Node[root].lchild, x, newdata);
search(Node[root].rchild, x, newdata);
}
//插入
void insert(int &root, int x){
if(root == -1){
root = newnode(x);
return;
}
if(应该插在左子树)
insert(Node[root].lchild, x);
else
insert(Node[root].rchild, x);
}
//建立二叉树
int create(int data[], int n){
int root = -1;
for(int i = 0; i < n; i++){
insert(root, data[i]);
}
return root;
}
一般的树
存储
struct node{
typename data;
vector<int> child;
}Node[maxn];
//如果不涉及数据域,可以写成vector<int> child[maxn]
新建结点
int index = 0;
int newnode(int x){
Node[index].data = x;
Node[index].child.clear();
return index++;
}
遍历
- 先根遍历
void preorder(int root){
printf("%d",Node[root].data);
for(int i = 0; i < Node[root].child.size(); i++){
preorder(Node[root].child[i]);
}
}
- 层序遍历
//如果添加layer呢?
void layerorder(int root){
queue<int> q;
q.push(root);
while(!q.empty()){
int front = q.front();
printf("%d",Node[front].data);
q.pop();
for(int i = 0; i < Node[front].child.size(); i++){
q.push(Node[front].child[i]);
}
}
}