树结构——非线性结构组织数据。
直观地,树结构是以分支关系定义的一种层次结构。即树结构组织起来的数据具有层次关系。而这种特性的数据在计算机中应用的非常广泛。如:操作系统中的文件管理、数据库系统中的索引、编译系统中的语法树等数据都是用树形结构组织的。
一、树的概念
树定义为:树是有n(n大于等于0)个结点组成的有穷集合。在任意一颗非空树种:
- 有且仅有一个称为根(root)的结点;
- 当n大于1时,其余的结点分为m(m大于0)个互不相交的有限集,T1,T2,......,Tm。其中,每一个集合本身又是一棵树,并称为根的子树(SubTree)。
二、二叉树结构概念
二叉树:一种树状结构,一棵二叉树的“结点”(Node)最多只能拥有2个子结点,也就是度小于或等于2。
定义如下:
1)二叉树的结点个数是有限,而且可以没有结点。
2)一棵二叉树的树根下可以分为两个子树称为“左子树”(Left Subtree)和“右子树”(Right Subtree)
二叉树链表结构表示法
是使用动态内存分配创建二叉树,我们使用结点结构的左、右指针变量字段链接树状结构的父节点与子结点。所以除了存储结点的基本数据外,每一个二叉树结点至少应该拥有两个字段存放左子树和右子树的指针。
二叉树使用的基本结构声明如下:
typedef struct tree
{
int data;
struct tree* left;
struct tree* right;
}treenode, *btree;
data是存储二叉树结点的数据,
left和right分别存储的是左子树和右子树的结构指针地址。
三、 二叉树的创建
代码如下如下:
/*
file name: btree.h
Anthor:
*/
typedef struct tree
{
int data;
struct tree* left;
struct tree* right;
}treenode, *btree;
/*
File Name: btree.c
Author:
*/
#include <stdio.h>
#include <stdlib.h>
#include "btree.h"
//插入新结点到二叉树中
btree insert_node(btree root, int value)
{
btree newnode; //树根指针
btree current; //目前树结点指针
btree back; //父结点指针
newnode = (btree)malloc(sizeof(treenode));
newnode->data = value;
newnode->left = NULL;
newnode->right = NULL;
if(NULL == root)
{
return newnode;
}
else
{
current = root;
while(current != NULL)
{
back = current;
if(current->data > value)
current = current->left;
else
current = current->right;
}
if(back->data > value)
back->left = newnode;
else
back->right = newnode;
}
return root;
}
//创建二叉树
btree create_btree(int* data, int len)
{
btree root = NULL;
int i;
for(i = 0; i < len; i++)
{
root = insert_node(root, data[i]);
}
return root;
}
//输出二叉树的左右分支,没有完全输出二叉树
void print_btree(btree root)
{
btree ptr;
ptr = root->left;
printf("print the lefe subtree:\n");
while(ptr != NULL)
{
printf("[%2d]\n", ptr->data);
ptr = ptr->left;
}
ptr = root->right;
printf("print the right subtree:\n");
while(ptr != NULL)
{
printf("[%2d]\n", ptr->data);
ptr = ptr->right;
}
}
int main()
{
btree root = NULL;
int data[10] = {5, 6, 4, 8, 2, 3, 7, 1, 9};
root = create_btree(data, 9);
printf("树的结点内容\n");
print_btree(root);
system("pause");
return 0;
}
从二叉树的结构来看,无论从哪一个结点面对的都是向左或者向右的选择,整个遍历过程可以简化为持续的处理选择,直到没路可走为止。
所以二叉树的遍历可以通过递归来实现。根据递归函数中调用的顺序不同,可以分为如下三种不同的遍历方式,
- 中序遍历方式(Inorder Traversal)
- 前序遍历方式(Preorder Traversal)
- 后序遍历方式(Postorder Traversal)
下面对每种的遍历方式的代码实现进行介绍
1. 中序遍历
中序遍历的递归函数为inorder(),
递归操作的步骤如下:
step1:检查是否可以继续前进,即指针root不等于NULL
step2:如果可以前进,其处理方式如下:
a)递归调用inorder(root->left)往左走
b)处理当前的结点
c)递归调用inorder(root->right)往右走
//二叉树中序遍历
void inorder(btree root)
{
if(root != NULL)
{
inorder(root->left);
printf("[%2d]\n", root->data);
inorder(root->right);
}
}
2. 前序遍历
前序遍历的递归函数为preorder(),
递归操作的步骤如下:
step1:检查是否可以继续前进,即指针root不等于NULL
step2:如果可以前进,其处理方式如下:
a)处理当前的结点
b)递归调用preorder(root->left)往左走
c)递归调用preorder(root->right)往右走
//二叉树前序遍历
void preorder(btree root)
{
if(NULL != root)
{
printf("[%2d]\n",root->data);
preorder(root->left);
preorder(root->right);
}
}
3. 后序遍历
后序遍历的递归函数为postorder(),
递归操作的步骤如下:
step1:检查是否可以继续前进,即指针root不等于NULL
step2:如果可以前进,其处理方式如下:
a)递归调用postorder(root->left)往左走
b)递归调用postorder(root->right)往右走
c)处理当前的结点
//二叉树后序遍历
void postorder(btree root)
{
if(NULL != root)
{
postorder(root->left);
postorder(root->right);
printf("[%2d]\n",root->data);
}
}
主函数如下:
int main()
{
btree root = NULL;
int data[10] = {5, 6, 4, 8, 2, 3, 7, 1, 9};
root = create_btree(data, 9);
printf("树的结点内容\n");
print_btree(root);
printf("=================================\n");
printf("Inorder Traversal Result:\n");
inorder(root);
printf("Preorder Traversal Result:\n");
preorder(root);
printf("Postorder Traversal Result:\n");
postorder(root);
system("pause");
return 0;
}
内容来自于《数据结构C语言版》