C++資料結構之 --二叉樹簡單實現和4種遍歷
實驗目的:實現簡單的二叉樹!
標頭檔案:
二叉樹.h
#ifndef 二叉樹_h__
#define 二叉樹_h__
#include <iostream>
#include <queue>
template<class T> class BinaryTree;//二叉樹的宣告
/*樹的節點*/
template<class T>
class TreeNode{
public:
TreeNode<T> *leftChild;
TreeNode<T> *rightChild;
T data;
public:
TreeNode(){
leftChild = NULL;
rightChild = NULL;
}
};
//二叉樹的定義
template<class T>
class BinaryTree{
public:
TreeNode<T> *root;//頭節點
public:
void InOrder();//中序遍歷
void InOrder(TreeNode<T> *currentNode);
void PreOrder();//先序遍歷
void PreOrder(TreeNode<T> *currentNode);
void EndOrder();//後序遍歷
void EndOrder(TreeNode<T> *currentNode);
void LevelOrder();//層序遍歷
void LevelOrder(TreeNode<T> *currentNode);
void Visit(TreeNode<T> *currentNode);//訪問當前節點
};
template<class T>
void BinaryTree<T>::LevelOrder(){
std::cout << "層序遍歷:" << std::endl;
LevelOrder(root);
}
template<class T>
void BinaryTree<T>::LevelOrder(TreeNode<T> *currentNode){
//建立一個佇列
std::queue<TreeNode<T>*> q;
while(currentNode)
{
Visit(currentNode);
if (currentNode->leftChild)
{
q.push(currentNode->leftChild);
}
if (currentNode->rightChild)
{
q.push(currentNode->rightChild);
}
if (q.empty())
{
return;
}
//在彈出一個節點時,我們要先把它的左右孩子先放進佇列裡
currentNode = q.front();//取隊首的節點,
q.pop();
}
}
template<class T>
void BinaryTree<T>::Visit(TreeNode<T> *currentNode){
std::cout << currentNode->data << " ";
}
template<class T>
void BinaryTree<T>::EndOrder(){
std::cout << "後序遍歷:" << std::endl;
EndOrder(root);
}
template<class T>
void BinaryTree<T>::EndOrder(TreeNode<T> *currentNode)
{
if (currentNode)
{
EndOrder(currentNode->leftChild);
EndOrder(currentNode->rightChild);
Visit(currentNode);
}
}
template<class T>
void BinaryTree<T>::PreOrder(){
std::cout << "先序遍歷:" << std::endl;
PreOrder(root);
}
template<class T>
void BinaryTree<T>::PreOrder(TreeNode<T> *currentNode){
if (currentNode)
{
Visit(currentNode);
PreOrder(currentNode->leftChild);
PreOrder(currentNode->rightChild);
}
}
template<class T>
void BinaryTree<T>::InOrder(){
std::cout << "中序遍歷:" << std::endl;
InOrder(root);
}
template<class T>
void BinaryTree<T>::InOrder(TreeNode<T> *currentNode){
if (currentNode)
{
InOrder(currentNode->leftChild);
//顯示當前節點
Visit(currentNode);
InOrder(currentNode->rightChild);
}
}
#endif // 二叉樹_h__
/* 遍歷的規則:
中序遍歷:左子樹-節點-右子樹
先序遍歷:節點-左子樹-右子樹
後序遍歷:左子樹-右子樹-節點
層序遍歷:一層一層遍歷
*/
實驗的二叉樹圖
原始檔
main.cpp
#include <iostream>
#include "二叉樹.h"
using namespace std;
int main(int argc,const char* argv[]){
cout << "你好,每一天" << endl;
/*構造二叉樹*/
TreeNode<int> a1;
a1.data = 1;
TreeNode<int> b2;
b2.data = 2;
TreeNode<int> c3;
c3.data = 3;
TreeNode<int> d4;
d4.data = 4;
TreeNode<int> e5;
e5.data = 5;
TreeNode<int> f6;
f6.data = 6;
TreeNode<int> g7;
g7.data = 7;
TreeNode<int> h8;
h8.data = 8;
TreeNode<int> i9;
i9.data = 9;
/*建立二叉樹*/
BinaryTree<int> binaryTree;
binaryTree.root = &a1;
a1.leftChild = &b2;
a1.rightChild = &c3;
b2.leftChild = &d4;
b2.rightChild = &e5;
e5.leftChild = &g7;
e5.rightChild = &h8;
c3.leftChild = &f6;
f6.rightChild = &i9;
/*先序遍歷*/
binaryTree.PreOrder();
cout <<endl;
/*中序遍歷*/
binaryTree.InOrder();
cout <<endl;
/*後序遍歷*/
binaryTree.EndOrder();
cout << endl;
/*層序遍歷*/
binaryTree.LevelOrder();
system("pause");
return 0;
}
實驗結果:
總結:
二叉樹:只要有頭節點(root),就可以確定一個二叉樹了。
節點:每一個節點,都有 value,leftfchild,rightchild.
層序遍歷時需要藉助佇列。
第二篇:二叉樹的簡單實現和4種遍歷操作
#pragma once
#ifndef NODE_H
#define NODE_H
class Node
{
public:
friend class BinaryTree;
Node();
Node(int item);
~Node();
//設定Value
void setData(int item);
int getData();
//設定leftChild
void setLeft(Node* left);
Node* getLeft();
//設定rightChild
void setRight(Node* right);
Node* getRight();
private:
Node* left;
Node* right;
int data;
};
#endif
#include "Node.h"
Node::Node(){}
Node::Node(int item)
{
this->data = item;
this->left = nullptr;
this->right = nullptr;
}
Node::~Node(){}
void Node::setData(int item){
this->data = item;
}
int Node::getData(){
return this->data;
}
void Node::setLeft(Node* left){
this->left = left;
}
Node* Node::getLeft(){
return this->left;
}
void Node::setRight(Node* right){
this->right = right;
}
Node* Node::getRight(){
return this->right;
}
#pragma once
#ifndef BinaryTree_h__
#define BinaryTree_h__
#include "Node.h"
class BinaryTree
{
public:
//構造器
BinaryTree();
~BinaryTree();
//獲取根節點
Node* getRoot();
//建立一棵二叉樹
void CreatBinaryTree();
//新增節點函式
void addNode(Node* newNode,Node* itemroot);
//先根遍歷
void preOrder(Node* t);
//中根遍歷
void inOrder(Node* t);
//後根遍歷
void postOrder(Node* t);
//層序遍歷
void levelOrder(Node* t);
//尋找data為item的節點
Node* findData(Node* t, int item);
//尋找給定節點的父節點
Node* returnFather(Node* t, Node *p);
//刪除t節點及其左右子樹
void deleteSubTree(Node* t);
private:
//判斷新增節點是否比根小
bool toLeft(int a, int b);
//判斷新增的節點是否比根大
bool toRight(int a, int b);
//刪除節點和節點的左右子樹
void deletAll(Node* t);
//頭節點
Node* root;
};
#endif // BinaryTree_h__
#include "BinaryTree.h"
#include <iostream>
#include <queue>
using namespace std;
BinaryTree::BinaryTree(){ root = nullptr; }
BinaryTree::~BinaryTree(){}
//獲取根節點
Node* BinaryTree::getRoot(){ return root; }
void BinaryTree::CreatBinaryTree() //建立一棵二叉樹
{
cout << "以此輸入number(按“字母”退出)" << endl;
int intValue;
Node* current;
while (cin >> intValue)
{
current = new Node(intValue);//構造新的節點
if (root==nullptr)
root = current;
else
addNode(current,root);
}
}
//新增節點函式
void BinaryTree::addNode(Node* newNode, Node* root)
{
//判斷是否新增到左子樹
if (toLeft(newNode->data, root->data))
{
if (root->left == nullptr)
{
root->left = newNode;
}
else
{
addNode(newNode, root->left);
}
}
else if (toRight(newNode->data, root->data))
{
if (root->right == nullptr)
{
root->right = newNode;
}
else
{
addNode(newNode, root->right);
}
}
}
void BinaryTree::preOrder(Node* t)//先根遍歷
{
if (t!=nullptr)
{
cout << t->getData() <<" ";
preOrder(t->getLeft());
preOrder(t->getRight());
}
}
void BinaryTree::inOrder(Node* t)//中根遍歷
{
if (t!=nullptr)
{
inOrder(t->getLeft());
cout << t->getData() << " ";
inOrder(t->getRight());
}
}
void BinaryTree::postOrder(Node* t)//後根遍歷
{
if (t!=nullptr)
{
postOrder(t->getLeft());
postOrder(t->getRight());
cout << t->getData() << " ";
}
}
//層序遍歷
void BinaryTree::levelOrder(Node* t){
//先建立一個佇列
queue<Node*> myQueue;
while (t!=nullptr)
{
cout << t->data << " ";//先列印它的值
//把左孩子放進去
if (t->left!=nullptr)
{
myQueue.push(t->left);
}
//把有孩子放進去
if (t->right!=nullptr)
{
myQueue.push(t->right);
}
if (myQueue.empty())
{
return;
}
//獲取當前的節點
t = myQueue.front();
myQueue.pop();
}
}
//尋找data為item的節點
Node* BinaryTree::findData(Node* t, int item)
{
Node* p;
if (t==nullptr)
{
return nullptr;
}else if (t->getData()==item)
{
return t;
}else if ((p=findData(t->getLeft(),item))!=nullptr)
{
return p;
}
else
{
return findData(t->getRight(), item);
}
}
//尋找給定節點的父節點
Node* BinaryTree::returnFather(Node* t, Node *p)
{
Node* q;
if (t==nullptr || p==nullptr)
{
return nullptr;
}
else if (t->getLeft()==p || t->getRight()==p)
{
return t;
}else if ((q=returnFather(t->getLeft(),p))!=nullptr)
{
return q;
}
else
{
return returnFather(t->getRight(),p);
}
}
//刪除t節點及其左右子樹
void BinaryTree::deleteSubTree(Node* t)
{
if (t==nullptr)
{
return;
}else if (t==root)
{
deletAll(t);
root = nullptr;
return;
}
Node* p, *q;
p = t;
q = returnFather(root, p);
if (q)
{
if ((q->getLeft())==p)
{
q->setLeft(nullptr);
}
else
{
q->setRight(nullptr);
}
}
deletAll(p);
}
//判斷新增節點是否比根小
bool BinaryTree::toLeft(int newItemValue, int rootValue)
{
if (newItemValue<rootValue)
{
return true;
}
else
{
return false;
}
}
//判斷新增的節點是否比根大
bool BinaryTree::toRight(int newItemValue, int rootValue)
{
if (newItemValue>rootValue)
{
return true;
}
else
{
return false;
}
}
//無情幹掉子節點和左右子樹
void BinaryTree::deletAll(Node* t)
{
if (t!=nullptr)
{
deletAll(t->getLeft());
deletAll(t->getRight());
delete t;
}
}
#include <iostream>
#include "BinaryTree.h"
using namespace std;
int main(){
BinaryTree binaryTree;
binaryTree.CreatBinaryTree();
cout << "先序遍歷結果:" <<" ";
binaryTree.preOrder(binaryTree.getRoot());
cout << endl;
cout << "中序遍歷結果:" << " ";
binaryTree.inOrder(binaryTree.getRoot());
cout << endl;
cout << "後序遍歷結果:" << " ";
binaryTree.postOrder(binaryTree.getRoot());
cout << endl;
cout << "層序遍歷結果:" << " ";
binaryTree.levelOrder(binaryTree.getRoot());
cout << endl;
Node* test;
test = binaryTree.findData(binaryTree.getRoot(), 2);
Node* test2;
test2 = binaryTree.returnFather(binaryTree.getRoot(), test);
cout << test2->getData() << endl;
binaryTree.deleteSubTree(test);
cout << "刪除後中根遍歷結果:" << " ";
binaryTree.inOrder(binaryTree.getRoot());
cout << endl;
system("pause");
return 0;
}