Linked binary tree search, traversal (recursive implementation) and other interface implementation

Table of contents

Foreword:

One: the establishment of binary tree

(1) The binary tree representation method used in this paper

(2) Manually build a binary tree

Two: Traversal of the binary tree

(1) Three traversal methods of binary tree

(2) Divide and conquer thought

(3) Preorder traversal

 (4) Inorder traversal

(5) Post-order traversal

Three: Find the node and height (depth) of the binary tree

(1) Find the binary tree node

①Find all the nodes of the binary tree

② Find the leaf node of the binary tree

③ Find the number of nodes in the kth layer of the binary tree

(2) Find the height (depth) of the binary tree

Four: Binary tree search


Foreword:

Before we briefly explained the binary tree and implemented a special binary tree such as a heap. This time we will implement the traversal of the chained binary tree (a very important part of the chained binary tree), search and other functions.

Attached is a link to the binary tree for the first time: http://t.csdn.cn/pMOia

One: the establishment of binary tree

(1) The binary tree representation method used in this paper

①Each node is a structure.

② In addition to storing data , each node also stores the address (structure pointer) of its own child node.

③ If the node has no children, it points to empty .

Schematic diagram:

code:

typedef char BTDataType;

typedef struct BinaryTreeNode
{
	//存储左孩子的地址
	struct BinaryTreeNode* left;
	//存储右孩子的地址
	struct BinaryTreeNode* right;
	BTDataType data;
}BTNode;

(2) Manually build a binary tree

① Call the malloc ( ) function to apply for space and insert data.

②Link the nodes in turn .

③Because it is necessary to apply for space and insert data multiple times, we encapsulate this part into the function BuyNewNode( ).

code:

//申请新节点
BTNode* BuyNewNode(BTDataType x)
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL)
	{
		printf("malloc error\n");
		exit(-1);
	}

	newnode->data = x;
	newnode->left = newnode->right = NULL;
	
	return newnode;
}


void test1()
{
    //手动建立一个二叉树
	BTNode* nodeA = BuyNewNode('A');
	BTNode* nodeB = BuyNewNode('B');
	BTNode* nodeC = BuyNewNode('C');
	nodeA->left = nodeB;
	nodeA->right = nodeC;
	BTNode* nodeD = BuyNewNode('D');
	BTNode* nodeE = BuyNewNode('E');
	BTNode* nodeF = BuyNewNode('F');
	nodeB->left = nodeD;
	nodeC->left = nodeE;
	nodeC->right = nodeF;
}

A graph of this binary tree:

Two: Traversal of the binary tree

(1) Three traversal methods of binary tree

1. Preorder traversal (Preorder Traversal, also known as preorder traversal ) - the operation of accessing the root node occurs when traversing its left and right
before the subtree .
2. Inorder Traversal (Inorder Traversal) - the operation of accessing the root node occurs in traversing its left and right subtrees
(between).
3. Postorder Traversal —— The operation of visiting the root node occurs after traversing its left and right subtrees .

(2) Divide and conquer thought

Divide and conquer is divide and conquer , which roughly means to turn a seemingly complicated problem into simple small problems, and finally solve the problem , which is also the core of this article.
For example, if a school wants to count the number of students, it can ask the headmaster to count them one by one, or let the headmaster tell the grade teacher, the head teacher tell the head teacher, and the head teacher tell the dormitory head.

(3) Preorder traversal

 Let's look at this binary tree, if we want to perform preorder traversal.

Print A first, and then traverse the left subtree of A.

Print B, traverse the left subtree of B.

Print D, traverse the left subtree of D.

If it is empty, traverse the right subtree of D.

If it is empty, the traversal of B's ​​left subtree ends, and B's right subtree is traversed.

If it is empty, the traversal of the left subtree of A ends, and the right subtree of A is traversed.

……………………

②It is not difficult to find that if we want to traverse the whole tree in preorder ,

It can be transformed into visiting A first and then traversing the left subtree and right subtree of A in preorder ,

Preorder traversal of the left subtree of A can be transformed into visiting B first and then preorder traversing the left subtree and right subtree of B ,

Pre-order traversal of the right subtree of B can be transformed into visiting D first and then pre-order traversal of the left and right subtrees of D , which can transform a larger problem into a very small problem.

code:

//前序遍历
void PreOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("空  ");
		return;
	}

	//打印
	printf("%c  ", root->data);
	//左子树
	PreOrder(root->left);
	//右子树
	PreOrder(root->right);
}

If you encounter this kind of recursion and don't understand it, you can draw a recursive expansion diagram :

 (4) Inorder traversal

If you want to perform an in-order traversal on this binary tree.

First traverse the left subtree of A.

Traverse the left subtree of B.

Traverse the left subtree of D.

Empty, print D, and traverse the right subtree of D.

Empty, print B, and traverse the right subtree of B.

Empty, print A, and traverse the right subtree of A.

………………

②Traverse the entire tree in order,

It can be transformed into visiting A after traversing the left subtree of A in inorder, and then traversing the right subtree in inorder ,

Inorder traversal of the left subtree of A can be transformed into inorder traversal of the left subtree of B and then visit B, and then inorder traversal of the right subtree ,

In-order traversal of the right subtree of B can be transformed into in-order traversal of the left subtree of D and then access to D, and then in-order traversal of the right subtree , which can turn a larger problem into a very small problem.

code:

//中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("空  ");
		return;
	}

	//左树
	InOrder(root->left);
	//打印
	printf("%c  ", root->data);
	//右树
	InOrder(root->right);
}

Recursive expansion diagram:

(5) Post-order traversal

If you want to perform post-order traversal on this binary tree.

First traverse the left subtree of A.

Traverse the left subtree of B.

Traverse the left subtree of D.

Empty, traverse the right subtree of D.

Empty, print D, and traverse the right subtree of B.

Empty, print B, and traverse the right subtree of A.

……………………

②Post-order traversal of the entire tree,

It can be transformed into post-order traversal of A's left subtree and right subtree to visit A ,

Post-order traversal of the left subtree of A can be transformed into post-order traversal of the left and right subtrees of B and then accessing B.

Post-order traversal of the right subtree of B can be transformed into post-order traversal of the left and right subtrees of D and then visit D , which can transform a larger problem into a very small problem.

code:

//后序遍历
void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("空  ");
		return;
	}
	//左树
	PostOrder(root->left);
	//右树
	PostOrder(root->right);
	//打印
	printf("%c  ", root->data);
}

Recursive expansion diagram:

Three: Find the node and height (depth) of the binary tree

(1) Find the binary tree node

①Find all the nodes of the binary tree

Ideas:

① A node is considered as long as the node address is not empty.

②To find the whole tree node , it can be transformed into the number of nodes in the left subtree of A plus the number of nodes in the right subtree of A plus 1 .

The number of nodes in the left subtree of A can be converted into the number of nodes in the left subtree of B plus the number of nodes in the right subtree of B plus 1 .

The number of nodes in the left subtree of B can be converted into the number of nodes in the left subtree of D plus the number of nodes in the right subtree of D plus 1 .

The left and right subtrees of D are empty, and the number of nodes in the left subtree of B is 1 .

………………………………

code:

//求树的节点数
int BinaryTreeSize(BTNode* root)
{
	/*if (root == NULL)
	{
		return 0;
	}
	return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;*/
	//更加简洁的写法
	return root == NULL ? 0 :
		BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

Recursive expansion diagram:

② Find the leaf node of the binary tree

Ideas:

A node whose left and right children are empty is counted as a leaf node .

② Finding the leaf nodes of the whole tree can be transformed into finding the leaf nodes of the left subtree of A and the leaf nodes of the right subtree of A.

Finding the leaf node of the left subtree of A can be transformed into finding the leaf node of the left subtree of B plus the leaf node of the right subtree of B.

The left and right children of D are all empty, and the leaf node of the left subtree of B is 1.

…………………………

code:

//求叶子节点
int BinaryLeafSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	if ((root->left == NULL) && (root->right == NULL))
	{
		return 1;
	}

	return BinaryLeafSize(root->left) + BinaryLeafSize(root->right);
}

Recursive expansion diagram:

③ Find the number of nodes in the kth layer of the binary tree

Ideas:

Suppose k is 3.

The number of nodes in the first layer of a tree is 1 .

②Empty node means that the number of nodes is 0 .

③ Finding the number of nodes in the third layer of the whole tree can be transformed into finding the sum of the number of nodes in the second layer of the left subtree and right subtree of A.

Finding the number of nodes in the second layer of the left subtree of A can be transformed into finding the sum of the number of nodes in the first layer of the left subtree and right subtree of B.

The left subtree of B is not empty, the number of layers is 1, and the number of nodes is 1 .

The right subtree of B is empty and the number of nodes is 0 .

………………………………

code:

//求第k层节点的个数
int BinaryTreeLevelKSize(BTNode* root,int k)
{
	//非法输入直接报错
	assert(k >= 1);

	if (root == NULL)
	{
		return 0;
	}

	if (k == 1)
	{
		return 1;
	}

	return BinaryTreeLevelKSize(root->left, k - 1)
		+ BinaryTreeLevelKSize(root->right, k - 1);
}

Recursive expansion diagram:

(2) Find the height (depth) of the binary tree

Ideas:

The height of an empty tree is 0 .

②The left and right children of a tree root node are all empty, and the height is 1 .

③The final height of a tree is the one with the greater depth among the left and right subtrees plus 1 .

④Finding the height of the whole tree can be transformed into adding 1 to the one with the greater height among the left and right subtrees of A.

Finding the height of the left subtree of A can be transformed into adding 1 to the height of the left and right subtrees of B.

Finding the height of the left subtree of B can be transformed into adding 1 to the height of the left and right subtrees of D.

The left and right children of D are empty, and the height of the left subtree of B is 1 .

The right subtree of B is an empty tree, and the height of B's ​​right subtree is 0 .

Take the larger side and add 1, and the height of the left subtree of A is 2 .

code:

//求二叉树的高度(深度)
int BinaryTreeDepth(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}

	if (root->left == NULL && root->right == NULL)
	{
		return 1;
	}

	return max(BinaryTreeDepth(root->left), BinaryTreeDepth(root->right)) + 1;
}

Recursive expansion diagram:

Four: Binary tree search

Function: Input the data x to be searched and return the address of the node .

Ideas:

Suppose to find E

①If found, return node address, if not found, return empty .

② When recursively calling, it is necessary to judge whether it is found according to the return value .

If it is not empty, it means that it has been found, and there is no need to continue searching, and the node address is returned .

③ Search for E in the whole tree, first check whether the root is E, not in the left and right subtrees of A.

First check whether the root of the left subtree of A is E, instead of searching in the left and right subtrees of B.

First check whether the root of the left subtree of B is E, instead of searching in the left and right subtrees of D.

If the left and right subtrees of D are empty, return empty.

If the right subtree of B is empty, return empty.

After searching the left subtree of A, if it is not found, search for the right subtree of A.

First check whether the root of the right subtree of A is E, not in the left and right subtrees of C.

………………………………

code:

//查找值为x的节点
BTNode* BianrtTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}

	if (root->data == x)
	{
		return root;
	}

	BTNode* leftRet = BianrtTreeFind(root->left,x);
	if (leftRet != NULL)
	{
		return leftRet;
	}

	BTNode* rightRet = BianrtTreeFind(root->right,x);
	if (rightRet != NULL)
	{
		return rightRet;
	}

	return NULL;
}

Recursively expand the graph (find E):

Guess you like

Origin blog.csdn.net/2301_76269963/article/details/130231257