Deletion and traversal of ordered binary trees

1. Deletion of binary trees
When deleting ordered binary tree nodes, you need to pay attention. After deletion, they will still be in order. What I follow here is: left>root>right! ! !
Binary deletion is divided into three situations. The overall idea is:
1) The deleted node has no children
It is best to analyze the situation without children. Deleting the node directly will not affect the order of the binary tree. It will still be in order after deletion.
2) The deleted node has a child (left child or right child)
You need to find the parent node of the deleted node and the child of the deleted node Connected to its parent node.
3) The deleted node has 2 children
You need to find the parent node of the deleted node and the smallest node in the entire tree. Exchange data between the smallest node and the deleted node, and then delete the smallest node.
2. Binary tree traversal methods
There are four main ways, namely: pre-order, mid-order, post-order, and level traversal. The first three are implemented in the program. The tree in the program is as follows:
Tree
The results of the three traversal methods are:
1. Preorder traversal: root, left , right, root node first, then left node, and finally right node. The result is: 45 90 99 91 87 55 77 23 35 14
2. In-order traversal: left, root, right.
The result is: 99 91 90 87 77 55 45 35 23 14
3. Post-order traversal: left, right, root.
The result is: 91 99 77 55 87 90 35 14 23 45
What needs to be noted is that the so-called front, middle and back are based on the root node. .
Program running results
Explanation: Level traversal follows from top to bottom, from left to right.
Level traversal instructions
The procedure is as follows:
1).cpp file

#include "stdafx.h"
#include"BinaryTree.h"

int _tmain(int argc, _TCHAR* argv[])
{
    
    
	BinaryTree<int>tree;
	tree.InsertNode(45);
	tree.InsertNode(23);
	tree.InsertNode(90);
	tree.InsertNode(87);
	tree.InsertNode(14);
	tree.InsertNode(99);
	tree.InsertNode(35);
	tree.InsertNode(55);
	tree.InsertNode(77);
	tree.InsertNode(91);

	tree.TravelNode(1);
	tree.TravelNode(0);
	tree.TravelNode(2);
	return 0;
}

2).h file

#pragma once
#include<memory>

template<class T>
class BinaryTree
{
    
    
	struct TreeNode
	{
    
    
		T data;//节点数据
		TreeNode* pleftChild;//左子节点
		TreeNode* prightChild;//右子节点
	};
public:
	BinaryTree();
	~BinaryTree();
	void InsertNode(const T&insertData);//插入节点

	void deleteNode(const T&delData);
	
	TreeNode* findNode(const T&findData);

	TreeNode* findMinNode();

	void TravelNode(int travelType);
private:
	void _InsertNode(TreeNode**root, const T&insertDara);

	void _deleteNode(TreeNode** root, const T&delData);

	TreeNode* _findParentNode(const T&findData);

	TreeNode* _findMinNode(TreeNode*root);

	TreeNode* pRoot;//根节点

	void _MidTravel(TreeNode* root);
	void _PreTravel(TreeNode* root);
	void _LstTravel(TreeNode* root);
};

template<class T>
BinaryTree<T>::BinaryTree()
{
    
    
	pRoot = NULL;
}

template<class T>
BinaryTree<T>::~BinaryTree()
{
    
    

}

template<class T>
void BinaryTree<T>::InsertNode(const T&insertData)
{
    
    
	_InsertNode(&pRoot, insertData);
}

template<class T>
void BinaryTree<T>::_InsertNode(TreeNode** pNode,const T& insertData)
{
    
    
	TreeNode *root = *pNode;

	if (!root)//当前节点不存在,为空
	{
    
    
		TreeNode* pNewNode = new TreeNode;//开辟一块新内存
		memset(pNewNode, 0x00, sizeof(TreeNode));//将新节点中数据置为0
		pNewNode->data = insertData;//将需要插入的数据作为新节点的数据

		*pNode = pNewNode;//将新节点与树连接起来
	}
	else//当前节点不为空
	{
    
    
		if (insertData>root->data)//大于在左子树
		{
    
    
			_InsertNode(&(root->pleftChild), insertData);
		}
		if (insertData<root->data)//小于在右子树
		{
    
    
			_InsertNode(&(root->prightChild), insertData);
		}
	}

}

template<class T>
void BinaryTree<T>::deleteNode(const T&delData)
{
    
    
	return _deleteNode(pRoot, delData);
}

template<class T>
void BinaryTree<T>::_deleteNode(TreeNode** root, const T&delData)
{
    
    
	if (root==0)
		return;
	TreeNode* pdelNode = findNode(delData);
	if (!pdelNode)
		return;
	TreeNode* pParentNode = _findParentNode(delData);
	/*
	分为三种情况:
	1、要删除的节点没有孩子   没有孩子的找需要删除节点的父节点,并将其孩子删掉
	2、要删除的节点有1个孩子  首先要找到需要删除的父节点。
	分为2种情况分析:
	(1)需要删除的节点是父节点左孩子,则被删除节点的孩子作为其父节点的某一个孩子
	(2)需要删除的节点是父节点左孩子,则被删除节点的孩子作为其父节点的某一个孩子                                      
	3、要删除的节点有2个孩子
	找到右子树中的最小节点,用这个节点替换要删除的节点,然后删除最小节点。
	*/
	if (pdelNode->pleftChild==0 && pdelNode->prightChild==0)//没有孩子,要删除的节点为叶子结点
	{
    
    
		if (pParentNode->pleftChild==pdelNode)
		{
    
    
			pParentNode->pleftChild = 0;
		}
		if (pParentNode->prightChild==pdelNode)
		{
    
    
			pParentNode->rightChild = 0;
		}
		delete pdelNode;
		pdelNode = 0;
		return;
	}
	else if (pdelNode->pleftChild==0||pdelNode->rightChild==0)//有一个孩子,左孩子或右孩子
	{
    
    
		if (pParentNode->pleftChild==pdelNode)//当要删除节点为左子节点
		{
    
    
			//将要删除的左节点的左孩子或者右孩子与要删除节点的父节点连接
			pParentNode->pleftChild = pdelNode->pleftChild ? pdelNode->pleftChild : pdelNode->prightChild;
		}
		else
		{
    
    
			//将要删除的右节点的左孩子或者右孩子与要删除节点的父节点连接
			pParentNode->prightChild = pdelNode->prightChild ? pdelNode->pleftChild : pdelNode->prightChild;
		}
		delete pdelNode;
		pdelNode = 0;
		return;
	}
	else//有2个孩子,将该子树的最小节点与要删除的节点互换,然后删除需要删除的节点
	{
    
    
		TreeNode* pMinNode = _findMinNode(pdelNode->prightChild);//找到最小节点

		TreeNode* pMinNodeParent = _findParentNode(pMinNode->data);//找到最小节点的父节点

		pdelNode->data = pMinNode->data;//数据互换

		pMinNodeParent->pleftChild = pMinNode->prightChild;//将最小节点作为被删除节点的左孩子

		delete pMinNode;
		pMinNode = 0;
		return;
	}
}

//寻找节点
template<class T>
typename BinaryTree<T>::TreeNode* BinaryTree<T>::findNode(const T&findData)
{
    
    
	TreeNode* pTempNode = pRoot;//将根节点赋值作为当前节点
	while (pTempNode)
	{
    
    
		if (pTempNode->data==findData)//找到根节点
		{
    
    
			return pTempNode;
		}

		if (pTempNode->data>findData)//左子树
		{
    
    
			pTempNode = pTempNode->pleftChild;
		}
		else//右子树
		{
    
    
			pTempNode = pTempNode->prightChild;
		}
	}
	return 0;
}
//寻找父节点
template<class T>
typename BinaryTree<T>::TreeNode* BinaryTree<T>::_findParentNode(const T&findData)
{
    
    
	TreeNode* pTempNode = pRoot;//将根节点作为当前节点
	TreeNode* pParentNode = pRoot;//根节点是父节点

	while (pTempNode)
	{
    
    
		if (pTempNode->data==findData)
		{
    
    
			return pParentNode;//找到该节点,返回父节点
		}

		pParentNode = pTempNode;//将当前节点为父节点,然后利用左右节点去继续判断
		if (pTempNode->data>findData)
		{
    
    
			pTempNode = pTempNode->pleftChild;
		}
		else
		{
    
    
			pTempNode = pTempNode->prightChild;
		}
	}
	return 0;
}

template<class T>
typename BinaryTree<T>::TreeNode* BinaryTree<T>::_findMinNode(TreeNode*root)
{
    
    
	if (root)
	{
    
    
		while (root->prightChild)//最小节点只可能在右子树上找到
		{
    
    
			root = root->prightChild;
		}
		return root;
	}
	return 0;
}

template<class T>
void BinaryTree<T>::TravelNode(int travelType)
{
    
    
	if (travelType==0)
	{
    
    
		cout << "中序遍历:";
		_MidTravel(pRoot);
		cout << endl;
	}
	if (travelType == 1)
	{
    
    
		cout << "前序遍历:";
		_PreTravel(pRoot);
		cout << endl;
	}
	if (travelType == 2)
	{
    
    
		cout << "后序遍历:";
		_LstTravel(pRoot);
		cout << endl;
	}
}

//中序遍历:左、根、右
template<class T>
void BinaryTree<T>::_MidTravel(TreeNode* root)
{
    
    
	if (root==0)
	{
    
    
		return;
	}

	_MidTravel(root->pleftChild);
	cout << root->data << " ";
	_MidTravel(root->prightChild);
}

//前序遍历 根、左、右
template<class T>
void BinaryTree<T>::_PreTravel(TreeNode* root)
{
    
    
	if (root == 0)
	{
    
    
		return;
	}

    cout << root->data << " ";
	_PreTravel(root->pleftChild);
	_PreTravel(root->prightChild);
}

//后序遍历 左、右、根
template<class T>
void BinaryTree<T>::_LstTravel(TreeNode* root)
{
    
    
	if (root == 0)
	{
    
    
		return;
	}

    _LstTravel(root->pleftChild);
	_LstTravel(root->prightChild);
	cout << root->data << " ";
	
}

Guess you like

Origin blog.csdn.net/appup/article/details/115510882