赞
踩
树形结构:一对多,第一个节点没有前驱,最后一个节点没有后继,中间节点有唯一前驱,可以有多个后继,也可以没有
由m(>=0)个互不相交的有限集合组成的集合
一个节点的子树个数称为该节点的度数。树的度数由树中最大的度数来决定。
度数为0的节点称为树叶,叶节点或终端节点。度数不为0的称为分支节点,除了根节点以外的分支节点称为内部节点。
路径:路径上的节点ki是ki+1的父节点(叶节点的个数也就是路径的个数)路径的长度称为边数。
层数:同一父节点的节点为同一层。根节点为第一层,树中节点的最大层数称为树的高度或者深度
树的左右节点有序,从左到右不可交换,则称为有序树
m(m>=0)棵互不相交的树的集合称为森林。树去掉根节点就称为森林
兄弟分为:亲兄弟,堂兄弟
二叉树的定义:二叉树是n(n>=0)个节点的有限集合,它或者是空集(n=0),或者是由一个根节点以及两棵不互相交的、分别称为左子树与柚子树的二叉树组成,二叉树与普通有序树不同,二叉树严格区分左孩子和右孩子,即使只有一个节点也要区分左右,度数最大为2.
性质:
第i层上的节点最多为2^(i-1)
知道最大层数,总的节点最多为2^i-1
树叶的数目比度数为2的节点的数目多1
(n0表示没有子节点的节点总数,n1表示有一个子节点的节点总数,n2表示有两个子节点的节点总数)
n=n0+n1+n2①
n=n1+2*n2+1②
n0=n2+1
满二叉树,每一层的孩子都存满(可以顺序存储,空间不浪费)
完全二叉树:只有最下面两层有度数小于2的节点,只有一个孩子时,孩子为左孩子
先将二叉树补成完全二叉树,再从上到下,从左到右将所有节点编号,依次存放在缓冲区中。
完全二叉树节点编号,从上到下,从左到右,根节点为一号,设节点数为n,某编号为i。
性质:
当i>1时,有父节点,其编号为i/2;
当2* i<=n时,有左孩子,其编号为2*i,否则没有左孩子,本身是叶节点;
当2* i+1<=n时,有右孩子,其编号为2*i+1,否则没右孩子,本身是叶节点;
当i为奇数(右节点)且不为1时,有左兄弟,其编号为i-1,否则没有左兄弟;
当i为偶数(左节点)且小于n时,有右兄弟,其编号为i+1,否则没有右兄弟
- /*===============================================
- * 文件名称:seqtree.c
- * 创 建 者:
- * 创建日期:2022年08月02日
- * 描 述:
- ================================================*/
- #include <stdio.h>
-
- int main(int argc, char *argv[])
- {
- char buf[16]={0},ch,i=1,n=1;
- printf("请输入完全二叉树的元素(#结束)\n");
- while((ch=getchar())!='#')//一个一个输入
- {
- buf[i]=ch;
- i++;
- }
- for(i=0;i<16;i++)//显示
- {
- if(i>n-1)
- {
- puts("");
- n=2*n;
- }
- if(buf[i]=='@')
- {
- printf(" ");
- continue;
- }
- printf("%c",buf[i]);
- }
-
- puts("");
- return 0;
- }
树中每个节点相关的结构体:
- typedef int data_t;
- typedef struct tree_node
- {
- data_t data;//数据域
- struct tree_node *l_child;//左节点
- struct tree_node *r_child;//右节点
- }T_node;
先序遍历:根左右
中序遍历:左根右
后序遍历:左右根
二叉树的层次遍历:
根先入队,然后循环到队列为空。
入队:判断一次根的左右节点是否存在,存在就入队(先左后右)
出队:打印根的数据域,根出队
头文件定义了树的存储类型,结构体的设计,以及将要实现的功能函数。
- /*===============================================
- * 文件名称:linktree.h
- * 创 建 者:
- * 创建日期:2022年08月02日
- * 描 述:
- ================================================*/
-
- #ifndef __LINKTREE__
- #define __LINKTREE__
-
- typedef char data_t;
- typedef struct tree_node
- {
- data_t data;
- struct tree_node *l_child;
- struct tree_node *r_child;
- }T_node;
-
- T_node *Create_Linktree();//创建一个二叉树
-
- void Linktree_Show0(T_node *root);//先序遍历
-
- void Linktree_Show1(T_node *root);//中序遍历
-
- void Linktree_Show2(T_node *root);//后序遍历
-
- void Nooread(T_node *root);//层次遍历
-
- #endif
二叉树的难点在于创建时的递归调用。从终端输入一串数据以 '#' 结束,数据存储在缓冲区中,然后每次执行创建程序,读一个字符。判断是否是'#',如不是,则向堆区申请空间,把数据存入数据域,指针域则调用创建函数,形成递归,先创建左子树,再创建右子树,当读取到'#'时,标明没有子树。返回NULL。
三种常见的遍历方式先判断是否是空树,不是的话就按照对应的顺序来调用遍历函数,形成递归条件,都是在根节点时打印。
最后的层次遍历则利用到了队列,每一个根节点都判断是否有左右子树,有的话就入队,然后把队列的第一个节点也就是这一次循环的根节点打印,然后出队,因为只显示一遍,不需要循环队列。
- /*===============================================
- * 文件名称:linktree.c
- * 创 建 者:
- * 创建日期:2022年08月02日
- * 描 述:
- ================================================*/
- #include <stdio.h>
- #include <stdlib.h>
- #include "linktree.h"
-
- T_node *Create_Linktree()//创建一个二叉树
- {
- char x;
- //printf("请输入节点的值,#表示空\n");
- T_node *root;
- scanf("%c",&x);
- //printf("x=%c\n",x);
- //getchar();
- if(x!='#')
- {
- root=(T_node *)malloc(sizeof(T_node));
- if(NULL==root)
- {
- printf("nalloc error");
- return NULL;
- }
- root->data=x;
- root->l_child=Create_Linktree();//先左后右
- root->r_child=Create_Linktree();
- return root;
- }
- else
- {
- return NULL;
- }
- }
-
- void Linktree_Show0(T_node *root)//先序遍历
- {
- if(root!=NULL) //根
- {
- printf("%4c",root->data);
-
- Linktree_Show0(root->l_child);//左
-
- Linktree_Show0(root->r_child);//右
- }
- return;
-
- }
- void Linktree_Show1(T_node *root)//中序遍历
- {
- if(root!=NULL) //根
- {
- Linktree_Show0(root->l_child);//左
- printf("%4c",root->data);
- Linktree_Show0(root->r_child);//右
- }
- return;
-
- }
- void Linktree_Show2(T_node *root)//后序遍历
- {
- if(root!=NULL) //根
- {
- Linktree_Show0(root->l_child);//左
-
- Linktree_Show0(root->r_child);//右
-
- printf("%4c",root->data);
- }
- return;
- }
- void Nooread(T_node *root)//层次遍历
- {
- int front,rear;//头尾指针
- T_node *q[16]; //指针数组
- if(root==NULL) //判断树是否为空
- {
- printf("空树无法遍历\n");
- return;
- }
- for(rear=1;rear<16;rear++)//给指针数组赋初值NULL
- {
- q[rear]=NULL;
- }
- front=rear=1;//下标为0的数组元素不用
- q[rear]=root;
- rear++;
- while(q[front]!=NULL)//队列为空则跳出循环
- {
- if(q[front]->l_child!=NULL)//左孩子存在则入队
- {
- q[rear]=q[front]->l_child;
- rear++; //rear后移
- }
- if(q[front]->r_child!=NULL)//右孩子存在则入队
- {
- q[rear]=q[front]->r_child;
- rear++; //rear后移
- }
- printf("%c",q[front]->data);//打印出队节点
- front++; //队头节点出队
- }
- }
主函数就调用了功能函数,先是创建了二叉树,然后四种遍历方式输出
- /*===============================================
- * 文件名称:main.c
- * 创 建 者:
- * 创建日期:2022年08月02日
- * 描 述:
- ================================================*/
- #include <stdio.h>
- #include "linktree.h"
-
- int main(int argc, char *argv[])
- {
- T_node *root=Create_Linktree();
- printf("-------------------------------------------\n");
- Linktree_Show0(root);
- printf("\n-------------------------------------------\n");
- Linktree_Show1(root);
- printf("\n-------------------------------------------\n");
- Linktree_Show2(root);
- printf("\n-------------------------------------------\n");
- Nooread(root);
- puts("");
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。