大部分笔记摘自《大话数据结构》与《数据结构》
一:相关定义
1、树是n个结点的有限集,n=0时称为空树。在任意一颗非空树中:(1)有且仅有一个特定的称为根的结点;(2)当n>1时,其余结点可分为m个互不相交的有限集,T1、T2、……、Tm,其中每一个集合本身又是一颗树,并且称为根的子树。
2、结点拥有的子树数称为结点的度,而树的度为结点的度的最大值。度为0的结点称为叶结点或终端结点,度不为0的结点称为分支结点、内部结点或非中断结点。
3、结点的子树的根称为结点的孩子,该结点称为孩子的双亲。同一双亲的为兄弟,祖先就是双亲一直往上一直到达根结点。树的层次数叫做树的深度或高度。
4、森林就是m课互不相交的树的集合,对于树中的每个结点而言,其子树的集合即为森林。
5、树的存储结构:双亲表示法、孩子表示法、孩子兄弟表示法。孩子兄弟表示法即设置两个指针分别指向该结点的第一个孩子和该结点的右兄弟,其最大的好处是将一颗复杂的树变成一颗二叉树。
6、一般来说,分等级的分类方案都可用层次结构来表示,即树结构。
二:叉树相关定义:
1、二叉树是n个结点的有限集合,该集合或者为空集(空二叉树),或者由一个根节点和两棵互不相交的、分别称为根结点的左子树或者右子树的二叉树组成。
2、每个结点最多只能有两棵子树,即度不大于2、左右子树有次序。
3、特殊的二叉树:斜树,只有左子树或者只有右子树;满二叉树,所有分支结点都满了;完全二叉树,由满二叉树往回砍的树。
三:
1、顺序存储结构对普通树这种一对多的关系结构实现起来比较复杂,但是二叉树是一种特殊的树,所以其用顺序结构也可以实现,不过顺序结构一般只用于完全二叉树,否则造成空间浪费。
2、二叉树每个结点最多有两个孩子,所以为它设计一个数据域和两个指针域就比较自然,这样的链表称为二叉链表(只有一个指针域我们称为单链表)。如果再加一个指向双亲的指针域,就称为三叉链表。
3、二叉树的遍历方法主要有:前序遍历、中序遍历、后序遍历、层次遍历等。
前序遍历:先访问结点,然后前序遍历左子树,最后遍历右子树。
中序遍历:中间访问结点
后序遍历:最后访问结点
实例一:二叉树的建立与遍历
#include "stdio.h" #include "malloc.h" // 二叉树结点 typedef struct BTnode { char data; struct BTnode *lchild,*rchild; }BTnode; /* * 功能:先序创建一个二叉链表 * 输入:无 * 输出:二叉链表的根结点 */ BTnode *create() { BTnode *node; // 结点指针 char ch = ' '; scanf("%c",&ch); if(ch == '#') // 用#号代替虚结点 node = NULL; else { node = (BTnode *)malloc(sizeof(BTnode)); // 分配一个新结点 node->data = ch; // 存储数据 node->lchild = create(); // 递归创建左子树结点 node->rchild = create(); // 递归创建右子树结点 } return node; // 返回根节点 } /* * 功能:先序遍历二叉树 * 输入:二叉链表的根节点 * 输出:无 */ void preOrderTraverse(BTnode *node) { if(node==NULL) // 如果结点为虚结点,则返回 return ; printf("%c",node->data); // 打印结点数据 preOrderTraverse(node->lchild); // 递归访问左子树结点 preOrderTraverse(node->rchild); // 递归访问右子树结点 } /* * 功能:中序遍历二叉树 * 输入:二叉链表的根节点 * 输出:无 */ void inOrderTraverse(BTnode *node) { if(node==NULL) return ; inOrderTraverse(node->lchild); printf("%c",node->data); inOrderTraverse(node->rchild); } /* * 功能:后序遍历二叉树 * 输入:二叉链表的根节点 * 输出:无 */ void postOrderTraverse(BTnode *node) { if(node==NULL) return ; postOrderTraverse(node->lchild); postOrderTraverse(node->rchild); printf("%c",node->data); } void main() { BTnode *root = create(); // 创建二叉链表,返回根节点 printf("\n"); printf("先序遍历:"); // 先序遍历二叉树 preOrderTraverse(root); printf("\n"); printf("中序遍历:"); // .. inOrderTraverse(root); printf("\n"); printf("后序遍历:"); // .. postOrderTraverse(root); printf("\n"); }
输入:abc##d##e#f##
其二叉树结构如图示:
打印结果:
关于树和二叉树的主要知识还有二叉树的一些性质、线索二叉树:把一颗二叉树原本指向虚结点的指针域指向前驱结点或后继结点,使其形成一个双向链表、树与二叉树,森林与二叉树的转换还有树和森林的遍历等。