数据结构 - (4)简单二叉树 插入及输出

一、概念

二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点  
 

二、完整代码

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

/*声明结点*/
typedef struct Node {
	int val;
	struct Node* lchild, * rchild;
}Node;


/*声明树*/
typedef struct Tree {
	int* root;
	int n;
}Tree;


/*初始化新结点*/
Node* getNewNode(int val) {
	Node* node = (Node*)malloc(sizeof(Node));
	node->val = val;
	node->lchild = node->rchild = NULL;
	return node;
}

/*初始化新树*/
Tree *getNewTree() {
	Tree* tree = (Tree*)malloc(sizeof(Tree));
	tree->n = 0;
	tree->root = NULL;
	return tree;
}


/*二叉排序树 插值法 (插入成功:ret = 1,否则:ret=0) [递归] */
Node *insertNode(Node *root,int val,int *ret) {
	if (root == NULL) {
		*ret = 1;
		/*初始化一个新结点,将结点插入树*/
		return getNewNode(val);
	}
	/*如果值相等,返回原树*/
	if (root->val == val)return root;
	/*左小右大*/
	if (root->val > val) {
		root->lchild = insertNode(root->lchild, val,ret);
	}
	else {
		root->rchild = insertNode(root->rchild, val,ret);
	}
	/*左小右大插完后,返回树结点(易遗漏)*/
	return root;
}


void insert(Tree* tree,int val) {
	if (tree == NULL)return;
	/*flag判断是否插入成功(0:失败,1:成功)*/
	int flag = 0;
	/*注意:插入节点后接收返回的树节点*/
	tree->root = insertNode(tree->root,val,&flag);//
	/*节点数+1*/
	tree->n += flag;
	return;
}


/*递归输出结点值 【广义表输出】*/
void outputNode(Node *root) {
	if (root == NULL)return;
	/*先输出根节点的数值*/
	printf("%d", root->val);
	/*判断并递归到左右子树,输出值*/
	if (root->lchild == NULL && root->rchild == NULL)return;
	printf("(");
	outputNode(root->lchild);
	printf(",");
	outputNode(root->rchild);
	printf(")");
}

/*输出树(调用输出结点)*/
void outputTree(Tree *tree) {
	if (tree == NULL)return;
	printf("tree(%d):", tree->n);
	outputNode(tree->root);
	printf("\n");
}

/*清除树结点*/
void clearNode(Node* node) {
	if (node == NULL)return;
	free(node->lchild);
	free(node->rchild);
	free(node);
	return;
}

/*清除树*/
void clearTree(Tree* tree) {
	if (tree == NULL)return;
	clearNode(tree->root);
	free(tree);
	return;
}


/// ////////////////////////////////前序遍历/////////////////////////

/*用了递归,并且要注意Node处判空操作*/
void preorderNode(Node* node) {
	if (node == NULL) return;
	printf("%d ", node->val);
	preorderNode(node->lchild);
	preorderNode(node->rchild);
	return;
}

void preorder(Tree *tree) {
	printf("pre order : ");
	preorderNode(tree->root);
	printf("\n");
	return;
}

////////////////////////////////////中序遍历/////////////////////////
void inorderNode(Node* node) {
	if (node == NULL) return;
	inorderNode(node->lchild);
	printf("%d ", node->val);
	inorderNode(node->rchild);
	return;
}

void inorder(Tree *tree) {
	printf("in order : ");
	inorderNode(tree->root);
	printf("\n");
	return;
}


/// ////////////////////////////////后序遍历/////////////////////////
void postorderNode(Node* node) {
	if (node == NULL) return;
	postorderNode(node->lchild);
	postorderNode(node->rchild);
	printf("%d ", node->val);
	return;
}

void postorder(Tree *tree) {
	printf("post order : ");
	postorderNode(tree->root);
	printf("\n");
	return;
}


int main()
{
	srand(time(0));
	/*先声明一个树*/
	Tree* tree = getNewTree();
	for (int i = 0; i < 10; i++) {
		int val = rand() % 100;
		insert(tree,val);
		/*每插入一个值,打印一次*/
		outputTree(tree);
	}
	printf("\n");
	preorder(tree);
	inorder(tree);
	postorder(tree);
	clearTree(tree);
	return 0;
}

 

三、分块理解

引入头文件,定义结点和数的数据类型
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

/*声明结点*/
typedef struct Node {
	int val;
	struct Node* lchild, * rchild;
}Node;


/*声明树*/
typedef struct Tree {
	int* root;
	int n;
}Tree;

初始化新结点和树(结点包含 值 和 左右子树,数则存放 根节点 及 节点数量)

/*初始化新结点*/
Node* getNewNode(int val) {
	Node* node = (Node*)malloc(sizeof(Node));
	node->val = val;
	node->lchild = node->rchild = NULL;
	return node;
}

/*初始化新树*/
Tree *getNewTree() {
	Tree* tree = (Tree*)malloc(sizeof(Tree));
	tree->n = 0;
	tree->root = NULL;
	return tree;
}

定义插入二叉树的方法(向二叉树内插入数值,采用 左小右大 的 插入方法 [二叉搜索树])这里需要用到递归,务必认真

/*二叉排序树 插值法 (插入成功:ret = 1,否则:ret=0) [递归] */
Node *insertNode(Node *root,int val,int *ret) {
	if (root == NULL) {
		*ret = 1;
		/*初始化一个新结点,将结点插入树*/
		return getNewNode(val);
	}
	/*如果值相等,返回原树*/
	if (root->val == val)return root;
	/*左小右大*/
	if (root->val > val) {
		root->lchild = insertNode(root->lchild, val,ret);
	}
	else {
		root->rchild = insertNode(root->rchild, val,ret);
	}
	/*左小右大插完后,返回树结点(易遗漏)*/
	return root;
}


void insert(Tree* tree,int val) {
	if (tree == NULL)return;
	/*flag判断是否插入成功(0:失败,1:成功)*/
	int flag = 0;
	/*注意:插入节点后接收返回的树节点*/
	tree->root = insertNode(tree->root,val,&flag);//
	/*节点数+1*/
	tree->n += flag;
	return;
}

通过递归将树打印出,同样需要细心

/*递归输出结点值 【广义表输出】*/
void outputNode(Node *root) {
	if (root == NULL)return;
	/*先输出根节点的数值*/
	printf("%d", root->val);
	/*判断并递归到左右子树,输出值*/
	if (root->lchild == NULL && root->rchild == NULL)return;
	printf("(");
	outputNode(root->lchild);
	printf(",");
	outputNode(root->rchild);
	printf(")");
}

/*输出树(调用输出结点)*/
void outputTree(Tree *tree) {
	if (tree == NULL)return;
	printf("tree(%d):", tree->n);
	outputNode(tree->root);
	printf("\n");
}

定义清除树的方法

/*清除树结点*/
void clearNode(Node* node) {
	if (node == NULL)return;
	free(node->lchild);
	free(node->rchild);
	free(node);
	return;
}

/*清除树*/
void clearTree(Tree* tree) {
	if (tree == NULL)return;
	clearNode(tree->root);
	free(tree);
	return;
}

前、中、后序遍历


/// ////////////////////////////////前序遍历/////////////////////////

/*用了递归,并且要注意Node处判空操作*/
void preorderNode(Node* node) {
	if (node == NULL) return;
	printf("%d ", node->val);
	preorderNode(node->lchild);
	preorderNode(node->rchild);
	return;
}

void preorder(Tree *tree) {
	printf("pre order : ");
	preorderNode(tree->root);
	printf("\n");
	return;
}

////////////////////////////////////中序遍历/////////////////////////
void inorderNode(Node* node) {
	if (node == NULL) return;
	inorderNode(node->lchild);
	printf("%d ", node->val);
	inorderNode(node->rchild);
	return;
}

void inorder(Tree *tree) {
	printf("in order : ");
	inorderNode(tree->root);
	printf("\n");
	return;
}


/// ////////////////////////////////后序遍历/////////////////////////
void postorderNode(Node* node) {
	if (node == NULL) return;
	postorderNode(node->lchild);
	postorderNode(node->rchild);
	printf("%d ", node->val);
	return;
}

void postorder(Tree *tree) {
	printf("post order : ");
	postorderNode(tree->root);
	printf("\n");
	return;
}

 

主函数:随机对树进行10次插值操作,再调用前中后序遍历,清空二叉树

int main()
{
	srand(time(0));
	/*先声明一个树*/
	Tree* tree = getNewTree();
	for (int i = 0; i < 10; i++) {
		int val = rand() % 100;
		insert(tree,val);
		/*每插入一个值,打印一次*/
		outputTree(tree);
	}
	printf("\n");
	preorder(tree);
	inorder(tree);
	postorder(tree);
	clearTree(tree);
	return 0;
}

 

posted @ 2022-04-14 12:00  HanaKoo  阅读(427)  评论(0编辑  收藏  举报
@format