这周我学习了树的有关知识,将学到的一些东西写下来。
FIRSt 树的定义
1、有且只有一个称为根的节点;
2、有若干个互不相交的子树,这些子树本身也是一颗树。
SECOND 专业术语
树的深度:从根节点到最低层,节点的层数 ,称之为树的深度。 根节点是第一层;
结点的层次:根节点为第一层,根节点的子节点为第2层,以此类推 ;
叶子节点:没有子节点的节点;
非终端节点:实际就是非叶子节点;
结点度: 子节点的个数称为度树的度。
THIRD 树的分类
一般树:任意一个节点的子节点的个数不受限制;
二叉树:任意一个节点的子节点最多2个,且子节点的位置不可更改;
满二叉树:在不增加层数的情况下,不能在增加节点的情况就是满二叉树;
完全二叉树:若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
介绍完树的基础知识后,我参考网上大神的代码,自己试了试二叉树的C语言建立与打印,代码如下:
二叉树的建立、插入与打印
#include <stdio.h>
#include <stdlib.h>
//二叉树的结点
typedef struct tree
{
struct tree *left;
struct tree *right;
int data;
}treenode,*Tree;
//二叉树结点的插入
Tree insert_node(Tree root,int node)
{
Tree newnode;//声明一个新节点
Tree tnode;//中间结点
Tree parentnode;
newnode=(Tree)malloc(sizeof(treenode));//申请空间
newnode->data=node;//给出的数据存在结点的数据域
newnode->right=NULL;
newnode->left=NULL;//左右为空
//如果树还是空的,返回新结点
if(root==NULL)
return newnode;
//否则进行插入
else{
tnode=root;
while(tnode!=NULL)
{
parentnode=tnode;
//进行判断 插入左或右
if((tnode->data)>node)
tnode=tnode->left;
else
tnode=tnode->right;
}
if(parentnode->data > node)
parentnode->left=newnode;
else
parentnode->right=newnode;
}
return root;
}
Tree create_btree(int *data,int len)
{
Tree root=NULL;
int i;
//遍历数组,将数组元素一一以插入的方式进行树的建立
for(i=0;i<len;i++)
root=insert_node(root,data[i]);
return root;
}
void print_btree(Tree root)
{
//递归遍历二叉树
if(root==NULL)
return;//终止条件
print_btree(root->left);
printf("%d\n",root->data);
print_btree(root->right);
}
int main()
{
Tree root=NULL;//建立一个Tree
int ans;//变量名,用于数组下标递增
int value;//二叉树的数据域
int nodelist[20];//存放二叉树数据
ans=0;
printf("请输入二叉树的数据(输入0结束)\n");
scanf("%d",&value);
while(value!=0){
nodelist[ans++]=value;
scanf("%d",&value);
}
root=create_btree(nodelist,ans);//创建二叉树
print_btree(root);//遍历打印二叉树
return 0;
}
通过树的学习,我对链表的认识又深了一层。并且想到一个问题:单向链表中的NEXT与二叉树里的左右子树,本质上讲是一样的。我又想到双向链表里的prev和next,那么链表是如何识别前后左右的呢?经过思考,我认为,可以将头结点或是父结点认为是一个质点(或是一个皮球),你可以在这个质点上进行连线,将你的新结点与之连接,而left、right、prev或是next只不过是连接用到的线,叫什么名字无所谓,这样书写只是更有助于理解。