赞
踩
目录
二叉树的创建方法有很多种,在这里我介绍两种:用括号表示法或扩展二叉树来创建二叉树。
扩号表示法(本质广义表)是树的一种表示。它的表示方法:将树的根结点写在括号的左边,除根结点之外的其余结点写在扩号中,并用逗号隔开。如下图:
解释:
1、A是根结点,写在扩号左边,其左右孩子为B,C,写成A(B,C)
2、B又是D、E的双亲结点(相当于B、D、E构成的树,B为根结点),故写成 B(D,E),带入上面A(B(D,E),C)
3、E有左孩子,但无右孩子,故写成E(G,),带入得A(B(D,E(G,)),C)
4、C有右孩子,但无左孩子,写成C(,F),带入得A(B(D,E(G,)),C(,F))
总结:这种写法总的来说就是,树根(左子树,右子树),其中左子树又有左子树和右子树,同样右子树有左子树和右子树,一直递归下去,直到叶子结点。
那怎么是用括号表示法的字符序列(上图的A(B(D,E(G,)),C(,F))) 创建二叉树,其算法思路如下:
(1)用str获取括号表示法表示二叉树的字符串
(2)用ch扫描str
(3)ch = '(' ,则将前面刚创建的结点作为双亲结点入栈,并置k = 1,表示其后创建的结点将作为这个结点的左孩子
(4)ch = ',' ,置k = 2,表示其后创建的结点为右孩子结点。
(5)ch = ')',表示栈顶元素的左右孩子结点处理完毕,出栈。
(6)其它情况创建一个结点,并根据 k 值,判断这个结点是栈中栈顶元素的左孩子还是右孩子,进行链接。
(7)一直循环下去直至str处理完成。
算法实现:
- /*栈的存储结构*/
- typedef struct Stack
- {
- BiTree data[Maxsize]; // 存放栈中元素
- int top; // 栈顶指针
- }SqStack;
- /*树的存储结构二叉链表*/
- typedef struct BiTNode
- {
- Elemtype data;
- struct BiTNode* lchild, * rchild;
- }BiTNode, * BiTree;
- /*初始化栈*/
- void InitStack(SqStack* S)
- {
- S->top = -1;
- }
- /*入栈*/
- bool Push(SqStack* S, BiTree x)
- {
- if (S->top == Maxsize - 1) // 栈满
- return false;
- S->data[++(S->top)] = x;
- return true;
- }
- /*出栈*/
- bool Pop(SqStack* S, BiTree* x)
- {
- if (S->top == -1) // 栈空
- return false;
- *x = S->data[(S->top)--];
- return true;
- }
- /*利用广义表构建二叉树*/
- void CreateBiTree2(BiTree* T, char* str)
- {
- SqStack S; // 辅助栈
- BiTree p = NULL, x; // 辅助指针
- InitStack(&S); // 初始化栈
- char ch;
- int i = 0, k;
- ch = str[i];
- while (ch != '\0') // str未扫描完时循环
- {
- switch (ch)
- {
- case '(': Push(&S, p); // 入栈,准备链接左孩子
- k = 1;
- break;
- case ')': Pop(&S, &x); // 出栈
- break;
- case ',': k = 2; // 准备链接右孩子
- break;
- default:
- p = (BiTree)malloc(sizeof(BiTNode));
- p->data = ch; p->lchild = p->rchild = NULL;
- if ((*T) == NULL) // p为二叉树的根结点
- (*T) = p;
- else // 已建立二叉树的根结点,根据k值链接左孩子还是右孩子
- {
- switch (k)
- {
- case 1: S.data[S.top]->lchild = p; break; // 链接左孩子
- case 2: S.data[S.top]->rchild = p; break; // 链接右孩子
- }
- }
- }
- i++;
- ch = str[i]; // 继续扫描str
- }
- }

我们用上图的括号表示法的字符串(A(B(D,E(G,)),C(,F)))来构建二叉树:
首先扫描到的A直接是其它情况,构建一个结点,并将A赋值给data,且创建的结点赋值给根结点T(由于刚开始树为空即T=NULL)
下一次扫描为 ( , A入栈,并且 k = 1(为A链接左孩子左准备),再次扫描下一个字符:
扫描的字符为B,创建结点并赋值,此时T != NULL(执行else语句块),根据 k = 1,栈顶元素(A)链接左孩子(即B)
扫描到 ( , 执行B入栈,k = 1
扫描到 D,创建结点赋值,然后根据 k = 1,栈顶(B)将D作为左孩子进行链接
扫描到 , ,k = 2,为栈顶元素(B)链接右孩子做准备
然后接着扫描,扫描到E,创建结点并赋值,根据 k = 2,将C作为右孩子,链接到栈顶元素(B)
扫描到 ( , 将E入栈,k = 1
扫描到 G,创建结点并赋值,根据 k = 1,将G作为左孩子,链接到栈顶元素(E)
扫描到 ,,k = 2,接着扫描
扫描到 ),栈顶元素(E)退栈,此时栈中有 B、A
又扫描到 ),栈顶元素(B)退栈,此时栈只有 A
扫描到,, k = 2,接着扫描
扫描到C,创建结点并赋值,根据 k = 2,C作为右孩子链接到栈顶元素(A)
扫描到 ( ,C入栈 k = 1
扫描到 ,k = 2,继续扫描
扫描到 F,创建节点并赋值,根据 k = 2,F作为右孩子链接到栈顶元素(C)
扫描到 (,进行退栈
又扫描到(,进行退栈
至此,扫描结束,栈为空,二叉树构建完成。
- // 输入 A(B(D,E(G,)),C(,F))
- #include <stdio.h>
- #include <stdbool.h>
- #include <stdlib.h>
-
- #define Maxsize 100
-
- typedef char Elemtype;
-
- /*树的存储结构二叉链表*/
- typedef struct BiTNode
- {
- Elemtype data;
- struct BiTNode* lchild, * rchild;
- }BiTNode, * BiTree;
-
- /*栈的存储结构*/
- typedef struct Stack
- {
- BiTree data[Maxsize]; // 存放栈中元素
- int top; // 栈顶指针
- }SqStack;
-
- /*初始化栈*/
- void InitStack(SqStack* S);
- /*入栈*/
- bool Push(SqStack* S, BiTree x);
- /*出栈*/
- bool Pop(SqStack* S, BiTree* x);
-
- /*利用广义表构建二叉树*/
- void CreateBiTree2(BiTree* T, char* str2);
-
- /*先序遍历*/
- void PreOrder(BiTree T);
-
- /*输出树结点*/
- void visit(BiTree T);
-
- /*以广义表输出二叉树*/
- void DispBiTree(BiTree T);
-
- /*获取一个由二叉树构成的广义表字符*/
- void GetStr(char* str);
-
- int main(void)
- {
- BiTree T = NULL;
- char str[50];
- GetStr(str);
- CreateBiTree2(&T, str);
- printf("二叉树的先序遍历:\n");
- PreOrder(T);
- printf("二叉树的括号表示法:");
- DispBiTree(T);
- return 0;
- }
-
- /*初始化栈*/
- void InitStack(SqStack* S)
- {
- S->top = -1;
- }
-
- /*入栈*/
- bool Push(SqStack* S, BiTree x)
- {
- if (S->top == Maxsize - 1) // 栈满
- return false;
- S->data[++(S->top)] = x;
- return true;
- }
-
- /*出栈*/
- bool Pop(SqStack* S, BiTree* x)
- {
- if (S->top == -1) // 栈空
- return false;
- *x = S->data[(S->top)--];
- return true;
- }
-
- /*利用广义表构建二叉树*/
- void CreateBiTree2(BiTree* T, char* str)
- {
- SqStack S; // 辅助栈
- BiTree p = NULL, x; // 辅助指针
- InitStack(&S); // 初始化栈
- char ch;
- int i = 0, k;
- ch = str[i];
- while (ch != '\0') // str未扫描完时循环
- {
- switch (ch)
- {
- case '(': Push(&S, p); // 入栈,准备链接左孩子
- k = 1;
- break;
- case ')': Pop(&S, &x); // 出栈
- break;
- case ',': k = 2; // 准备链接右孩子结点
- break;
- default:
- p = (BiTree)malloc(sizeof(BiTNode));
- p->data = ch; p->lchild = p->rchild = NULL;
- if ((*T) == NULL) // p为二叉树的根结点
- (*T) = p;
- else // 已建立二叉树的根结点,根据k值链接左孩子还是右孩子
- {
- switch (k)
- {
- case 1: S.data[S.top]->lchild = p; break; // 链接左孩子
- case 2: S.data[S.top]->rchild = p; break; // 链接右孩子
- }
- }
- }
- i++;
- ch = str[i]; // 继续扫描str
- }
- }
-
- /*先序遍历*/
- void PreOrder(BiTree T)
- {
- if (T != NULL)
- {
- visit(T);
- PreOrder(T->lchild);
- PreOrder(T->rchild);
- }
- }
-
- /*输出树结点*/
- void visit(BiTree T)
- {
- printf("树结点的值:%c\n", T->data);
- }
-
- /*获取一个由二叉树构成的广义表字符*/
- void GetStr(char* str)
- {
- printf("请输入由二叉树构成的广义表字符串:");
- scanf("%s", str);
- }
-
- /*以广义表输出二叉树*/
- void DispBiTree(BiTree T)
- {
- if (T != NULL)
- {
- printf("%c", T->data);
- if (T->lchild != NULL || T->rchild != NULL) //左右子树不为空
- {
- printf("(");
- DispBiTree(T->lchild); // 递归处理左子树
- if (T->rchild != NULL)
- printf(",");
- DispBiTree(T->rchild); //递归处理右子树
- printf(")");
- }
- }
- }

扩展二叉树:将二叉树中的每个结点的空指针引出一个虚结点,其值为一特值,比如"#",这种处理后的二叉树为原二叉树的扩展树。扩展二叉树就可以做到一个遍历序列确定一颗二叉树。如下图(前序遍历扩展二叉树,介绍的也是这种):
上图扩展二叉树的前序序列为:ABD##EG###C#F##.
总结:将二叉树变为扩展二叉树,就是将原二叉树的每一个一件的度都变为2,即都有左、右孩子。
算法思路:
(1)当 ch = '#',构建空指针,即(*T = NULL)
(2)ch != '#' ,创建新结点赋值,并进行递归构造左、右子树
算法实现:
- /*树的存储结构二叉链表*/
- typedef struct BiTNode
- {
- Elemtype data;
- struct BiTNode* lchild, * rchild;
- }BiTNode, * BiTree;
- /*利用一个前序遍历的扩展二叉树的字符串序列*/
- void CreateBiTree1(BiTree* T)
- {
- Elemtype ch;
-
- scanf("%c", &ch); //获取前序遍历的扩展二叉树的字符串的一个字符
-
- if (ch == '#')
- *T = NULL; // 空树结点
- else
- {
- *T = (BiTree)malloc(sizeof(BiTNode));
- if (!*T) // 未分配到空间
- exit(false);
- (*T)->data = ch; // 生成根结点
- (*T)->lchild = (*T)->rchild = NULL;
- CreateBiTree1(&(*T)->lchild); // 构造左子树
- CreateBiTree1(&(*T)->rchild); // 构造右子树
- }
- }

- // 输入 ABD##EG###C#F##
- #include <stdio.h>
- #include <stdbool.h>
- #include <stdlib.h>
-
- #define Maxsize 100
-
- typedef char Elemtype;
-
- /*树的存储结构二叉链表*/
- typedef struct BiTNode
- {
- Elemtype data;
- struct BiTNode* lchild, * rchild;
- }BiTNode, * BiTree;
-
- /*利用一个前序遍历的扩展二叉树的字符串序列*/
- void CreateBiTree1(BiTree* T);
-
- /*先序遍历*/
- void PreOrder(BiTree T);
-
- /*输出树结点*/
- void visit(BiTree T);
-
- int main(void)
- {
- BiTree T = NULL;
- printf("请输入前序遍历的扩展二叉树的字符序列:");
- CreateBiTree1(&T);
- printf("二叉树的先序遍历:\n");
- PreOrder(T);
- return 0;
- }
-
- /*利用一个前序遍历的扩展二叉树的字符串序列*/
- void CreateBiTree1(BiTree* T)
- {
- Elemtype ch;
-
- scanf("%c", &ch); //获取前序遍历的扩展二叉树的字符串的一个字符
-
- if (ch == '#')
- *T = NULL; // 空树结点
- else
- {
- *T = (BiTree)malloc(sizeof(BiTNode));
- if (!*T) // 未分配到空间
- exit(false);
- (*T)->data = ch; // 生成根结点
- (*T)->lchild = (*T)->rchild = NULL;
- CreateBiTree1(&(*T)->lchild); // 构造左子树
- CreateBiTree1(&(*T)->rchild); // 构造右子树
- }
- }
-
- /*先序遍历*/
- void PreOrder(BiTree T)
- {
- if (T != NULL)
- {
- visit(T);
- PreOrder(T->lchild);
- PreOrder(T->rchild);
- }
- }
-
- /*输出树结点*/
- void visit(BiTree T)
- {
- printf("树结点的值:%c\n", T->data);
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。