树的基本操作
老规矩,了解了树的基本概念之后,咱们还是先从基本操作代码开始,在代码中和树交朋友
注:
1.二叉树的结点结构体
2.初始化
3.左插入孩子结点
4.右插入孩子结点
5.前序、中序、后序遍历
6.查找数据元素
本文以书本上的一个例子加以演示,包含一个头文件《BiTree.h》和一个源文件《main.cpp》
建立这样一颗二叉树:
BiTree.h:
#pragma once
#include<stdio.h>
#include<stdlib.h>
typedef int DataType;
//二叉树的结点结构体
struct BiTreeNode
{
DataType data; //数据域
BiTreeNode *leftChild; //左孩子指针域
BiTreeNode *rightChild; //右孩子指针域
};
//初始化根结点
void initiate(BiTreeNode **root) {
*root = (BiTreeNode *)malloc(sizeof(BiTreeNode)); //根结点分配内存空间
(*root)->data = NULL;
(*root)->leftChild = NULL;
(*root)->rightChild = NULL;
}
/*结点curr左插入结点,成功返回插入好的结点,否则返回NULL
即将新的数据结点s变成curr的左孩子结点,curr以前的左孩子结点变成s的左孩子结点*/
BiTreeNode *insertLeftNode(BiTreeNode *curr,DataType data) {
BiTreeNode *s;
s = (BiTreeNode *)malloc(sizeof(BiTreeNode));
s->data = data; //用数据建立新的二叉树结点
if(curr == NULL) { //防止当前结点为空
printf("未找到目标结点!");
return NULL;
}
s->leftChild = curr->leftChild; //在curr的左子树变成s的左子树
s->rightChild = NULL; //默认新插入的结点的右孩子结点为NULL
curr->leftChild = s; //将s变成curr的左子树,因此被插入到树中
return s; //返回插入好的结点
}
/*结点curr右插入结点,成功返回插入好的结点,否则返回NULL
即将新的数据结点s变成curr的右孩子结点,curr以前的右孩子结点变成s的右孩子结点*/
BiTreeNode *insertRightNode(BiTreeNode *curr, DataType data) {
BiTreeNode *s;
s = (BiTreeNode *)malloc(sizeof(BiTreeNode));
s->data = data; //用数据建立新的二叉树结点
if (curr == NULL) { //防止当前结点为空
printf("未找到目标结点!");
return NULL;
}
s->leftChild = NULL; //默认新插入的结点的左孩子结点为NULL
s->rightChild = curr->rightChild; //在curr的右子树变成s的右子树
curr->rightChild = s; //将s变成curr的右子树,因此被插入到树中
return s; //返回插入好的结点
}
/*前序遍历 ,递归*/
void PreOrder(BiTreeNode *root) {
if (root != NULL ) {
if(root->data!=NULL) //先访问根结点
printf("%c ", root->data);
PreOrder(root->leftChild); //再访问左孩子结点
PreOrder(root->rightChild); //再访问右孩子结点
}
}
/*中序遍历*/
void InOrder(BiTreeNode *root) {
if (root != NULL) {
InOrder(root->leftChild); //先访问左孩子结点
if (root->data != NULL) //再访问根结点
printf("%c ", root->data);
InOrder(root->rightChild); //再访问右孩子结点
}
}
/*后序遍历*/
void PostOrder(BiTreeNode *root) {
if (root != NULL) {
PostOrder(root->leftChild); //先访问左孩子结点
PostOrder(root->rightChild); //再访问右孩子结点
if (root->data != NULL) //最后访问根结点
printf("%c ", root->data);
}
}
/*查找数据元素,递归调用,成功返回找到的结点,否则返回NULL*/
BiTreeNode *search(BiTreeNode *root,int data) {
BiTreeNode *result = NULL;
if (root != NULL) {
if (root->data == data) { //首先在根结点找
result = root;
}
else {//如果在根结点没找到
result = search(root->leftChild,data); //在左孩子结点找
if (result == NULL) //如果在左孩子结点没找到
result = search(root->rightChild, data); //在右孩子结点找
}
}
return result; //返回查找结果
}
main.c:
#include"BiTree.h" //因为在BiTree.h中带入了stdio.h,此处可不重复导入
int main()
{
BiTreeNode *root, *p;
initiate(&root); //初始化根结点
p = insertLeftNode(root, 'A'); //根结点左孩子插入A
p = insertLeftNode(p, 'B'); //A结点左孩子插入B
p = insertLeftNode(p, 'D'); //B结点左孩子插入D
p = insertRightNode(p, 'G'); //D结点左孩子插入G
p = insertRightNode(root->leftChild, 'C'); //A结点右孩子插入C
insertLeftNode(p, 'E'); //C结点左孩子插入E
insertRightNode(p, 'F'); //C结点右孩子插入F
/*三种遍历*/
printf("前序遍历:\n");
PreOrder(root);
printf("\n");
printf("中序遍历:\n");
InOrder(root);
printf("\n");
printf("后序遍历:\n");
PostOrder(root);
printf("\n");
/*查找F*/
p = search(root, 'F');
if (p != NULL) {
printf("已找到F元素!\n");
}
else
printf("未找到F元素!\n");
system("pause"); //暂停,防止闪屏
return 0;
}
运行结果:
代码编译器:Visual Studio 2017
ok