赞
踩
树,是有限节点的集合。生活中的树是树根在下面,数据结构中的树的根在顶部,如下图:
公司的人员组织架构,董事长,总经理,副总。。。,这种模型可以用二叉树表示,还有一些压缩算法也用到了树结构。
树的几个概念
(1)度:有几个直接的孩子,例如,A的度是3,它有BCD三个孩子,B的度是2,它有EF两个孩子,度为0的节点也就是叶子节点(终端节点)
(2)祖先:E的祖先是B,A , 从当前节点一直往上找
(3)叶子节点:下面的一层称为叶子节点,也可以称为终端节点。
(4)根:非叶子节点。
(5)树的深度,如下图
(6)森林:不交叉的几棵树在一起称为森林
所有节点的度都小于等于2的树称为二叉树。下面这几种都可以称为二叉树
1、二叉树的遍历
3种遍历方式,根据根节点的位置,分为前序,中序,后序。
前序:根左右,ABC
中序 :左根右, BAC
后序遍历:左右根, BCA
例如下面这颗二叉树
从根节点A在结果中的位置也可以看出是那种遍历方式。
2、二叉树的存储结构
(1)顺序存储,类似于数组,例如下面这颗二叉树,在数组中的存储是:3561972
数组存储时,如果节点不存在就用0表示,例如下面的,在数组中就是35019
顺序存储可以作为一种特殊形式,有相关需求时可以采用,
(2)链式存储,这是二叉树最好的存储形式,用一个结构体表示节点,有数据成员,指向左子树的指针,指向右子树的指针。
3、满二叉树与完全二叉树
完全二叉树的定义:如果二叉树的深度为h, 除h层外,其它各层的节点数都达到最大数,且第h层的所有节点都连续集中在最左边,这种二叉树称为完全二叉树。
下面介绍如何用数组和链表,例如实现下面这颗树
基于数组的二叉树实现
头文件TreeArray.h
- /*
- 用数组实现二叉树
- */
-
- #pragma once
-
- //节点的插入方向
- enum DIRECTION
- {
- LEFT,
- RIGHT
- };
-
- class TreeArray
- {
- public:
- TreeArray(int size, int *pRoot); //构造创建树
- ~TreeArray(); //销毁树
-
- int *SearchNode(int nodeIndex);
- bool AddNode(int nodeIndex, DIRECTION dirc, int *pNode);
- bool DeleteNode(int nodeIndex, int *pNode);
- void TreeTraverse(); //遍历树
-
- private:
- int *m_pTree;
- int m_iSize; //树的容量
- };
TreeArray.cpp
- #include "TreeArray.h"
- #include <iostream>
-
- using namespace std;
-
- TreeArray::TreeArray(int size,int *pRoot)
- {
- if (size > 0)
- {
- m_iSize = size;
- m_pTree = new int[size];
-
- for (int i = 0; i < size; i++)
- {
- m_pTree[i] = 0;
- }
-
- m_pTree[0] = *pRoot;
- }
- else
- {
- m_iSize = 0;
- m_pTree = nullptr;
- }
- }
-
- TreeArray::~TreeArray()
- {
- if (m_pTree != nullptr)
- {
- delete[] m_pTree;
- m_pTree = nullptr;
- }
- }
-
- int * TreeArray::SearchNode(int nodeIndex)
- {
- if (nodeIndex < m_iSize && m_pTree >= 0)
- {
- if (m_pTree[nodeIndex] == 0) //0表示空节点
- {
- return nullptr;
- }
- }
- else
- {
- return nullptr;
- }
-
- return &m_pTree[nodeIndex];
- }
-
- bool TreeArray::AddNode(int nodeIndex, DIRECTION dirc, int * pNode)
- {
- if (nodeIndex < 0 || nodeIndex >= m_iSize)
- {
- return false;
- }
-
- if (m_pTree[nodeIndex] == 0)
- {
- return false;
- }
-
- if (dirc == LEFT)
- {
- int insertId = nodeIndex * 2 + 1;
- if (insertId >= m_iSize)
- {
- return false;
- }
-
- if (m_pTree[insertId] != 0)
- {
- return false;
- }
-
- m_pTree[insertId] = *pNode;
- }
- else if (dirc == RIGHT)
- {
- int insertId = nodeIndex * 2 + 2;
- if (insertId >= m_iSize)
- {
- return false;
- }
-
- if (m_pTree[insertId] != 0)
- {
- return false;
- }
-
- m_pTree[insertId] = *pNode;
- }
-
- return true;
- }
-
- bool TreeArray::DeleteNode(int nodeIndex, int * pNode)
- {
- if (nodeIndex < 0 || nodeIndex >= m_iSize)
- {
- return false;
- }
-
- if (m_pTree[nodeIndex] == 0)
- {
- return false;
- }
-
- *pNode = m_pTree[nodeIndex];
- m_pTree[nodeIndex] = 0;
- return true;
- }
-
- void TreeArray::TreeTraverse()
- {
- for (int i = 0; i<m_iSize; i++)
- {
- cout << m_pTree[i] << " ";
- }
- cout << endl;
- }
main函数测试
- #include <iostream>
- #include "TreeArray.h"
-
- using namespace std;
-
- int main()
- {
- int root = 666;
- TreeArray *pTree = new TreeArray(10, &root);
- int node1 = 500;
- int node2 = 800;
- pTree->AddNode(0, LEFT, &node1);
- pTree->AddNode(0, RIGHT, &node2);
-
- int node3 = 200;
- int node4 = 600;
- pTree->AddNode(1, LEFT, &node3);
- pTree->AddNode(1, RIGHT, &node4);
-
- int node5 = 900;
- int node6 = 700;
- pTree->AddNode(2, LEFT, &node5);
- pTree->AddNode(2, RIGHT, &node6);
-
- //遍历
- pTree->TreeTraverse();
-
- //查找
- int *pValue = pTree->SearchNode(3);
- cout << "index = 3的节点值是" << *pValue << endl;
-
- //删除
- int dValue = 0;
- pTree->DeleteNode(6, &dValue);
-
- //遍历
- pTree->TreeTraverse();
-
- delete pTree;
- return 0;
- }
运行结果
基于链表的二叉树实现
用链表实现二叉树,得先定义好二叉树的节点类型,根据二叉树的性质,节点得有5个属性:索引、数据 、左孩子指针、右孩子指针 、父结点指针 。如下所示:
- struct Node
- {
- int index;
- int data;
- Node *pLChild; //左子树
- Node *pRChild; //右字数
- Node *pParent; //父节点
- };
还得实现3种遍历方式,使用递归遍历是比较方便的。具体代码如下
Tree.h
- #ifndef TREE_H
- #define TREE_H
-
- #include <iostream>
-
- using namespace std;
-
-
- //树的节点
- struct Node
- {
- Node(int _data = 0);
- Node *SearchNode(int nodeIndex);
- void DeleteNode();
- void PreOrderTraversal();
- void MiddleOrderTraversal();
- void LastOrderTraversal();
- int index;
- int data;
- Node *pLChild; //左子树
- Node *pRChild; //右字数
- Node *pParent; //父节点
- };
-
- //节点的插入方向
- enum DIRECTION
- {
- LEFT,
- RIGHT
- };
-
- //二叉树
- class Tree
- {
- public:
- Tree(int data = 0); //创建树
- ~Tree(); //销毁树
- Node *SearchNode(int nodeIndex); //搜索结点
- bool AddNode(int nodeIndex, DIRECTION direction, Node *pNode); //添加结点
- bool DeleteNode(int nodeIndex, Node *pNode); //删除结点
- void PreOrderTraversal(); //前序遍历
- void MiddleOrderTraversal(); //中序遍历
- void LastOrderTraversal(); //后序遍历
-
- private:
- Node *m_pRoot;
- };
-
- #endif
Tree.cpp
- #include "Tree.h"
-
- Node::Node(int _data)
- {
- index = 0;
- data = _data;
- pLChild = NULL;
- pRChild = NULL;
- pParent = NULL;
- }
-
- Node *Node::SearchNode(int nodeIndex)
- {
- if (this->index == nodeIndex)
- {
- return this;
- }
-
- Node *temp = NULL;
- if (this->pLChild != NULL)
- {
- if (this->pLChild->index == nodeIndex)
- {
- return this->pLChild;
- }
- else
- {
- temp = this->pLChild->SearchNode(nodeIndex);
- if (temp != NULL)
- {
- return temp;
- }
- }
- }
-
- if (this->pRChild != NULL)
- {
- if (this->pRChild->index == nodeIndex)
- {
- return this->pRChild;
- }
- else
- {
- temp = this->pRChild->SearchNode(nodeIndex);
- if (temp != NULL)
- {
- return temp;
- }
- }
- }
-
- return NULL;
- }
-
- void Node::DeleteNode()
- {
- if (this->pLChild != NULL)
- {
- this->pLChild->DeleteNode();
- }
- if (this->pRChild != NULL)
- {
- this->pRChild->DeleteNode();
- }
- if (this->pParent != NULL)
- {
- if (this->pParent->pLChild == this)
- {
- this->pParent->pLChild = NULL;
- }
- if (this->pParent->pRChild == this)
- {
- this->pParent->pRChild = NULL;
- }
- }
-
- delete this;
- }
-
- void Node::PreOrderTraversal()
- {
- cout << this->index << " " << this->data << endl;
- if (this->pLChild != NULL)
- {
- this->pLChild->PreOrderTraversal();
- }
- if (this->pRChild != NULL)
- {
- this->pRChild->PreOrderTraversal();
- }
- }
-
- void Node::MiddleOrderTraversal()
- {
-
- if (this->pLChild != NULL)
- {
- this->pLChild->MiddleOrderTraversal();
- }
-
- cout << this->index << " " << this->data << endl;
-
- if (this->pRChild != NULL)
- {
- this->pRChild->MiddleOrderTraversal();
- }
- }
-
- void Node::LastOrderTraversal()
- {
- if (this->pLChild != NULL)
- {
- this->pLChild->LastOrderTraversal();
- }
-
- if (this->pRChild != NULL)
- {
- this->pRChild->LastOrderTraversal();
- }
-
- cout << this->index << " " << this->data << endl;
- }
-
- Tree::Tree(int data)
- {
- m_pRoot = new Node(data);
- }
-
- Tree::~Tree()
- {
- //DeleteNode(0, NULL);
- m_pRoot->DeleteNode();
- }
-
- Node *Tree::SearchNode(int nodeIndex)
- {
- return m_pRoot->SearchNode(nodeIndex);
- }
-
- bool Tree::AddNode(int nodeIndex, DIRECTION direction, Node *pNode)
- {
- Node *temp = SearchNode(nodeIndex);
- if(temp == NULL)
- {
- return false;
- }
-
- Node *node = new Node();
- if(node == NULL)
- {
- return false;
- }
- node->index = pNode->index;
- node->data = pNode->data;
- node->pParent = temp;
-
- if(direction == LEFT)
- {
- temp->pLChild = node;
- }
-
- if(direction == RIGHT)
- {
- temp->pRChild = node;
- }
-
- return true;
-
- }
-
- bool Tree::DeleteNode(int nodeIndex, Node *pNode)
- {
- Node *temp = SearchNode(nodeIndex);
- if(temp == NULL)
- {
- return false;
- }
-
- if(pNode != NULL)
- {
- pNode->data = temp->data;
- }
-
- temp->DeleteNode();
- return true;
- }
-
- void Tree::PreOrderTraversal()
- {
- m_pRoot->PreOrderTraversal();
- }
-
- void Tree::MiddleOrderTraversal()
- {
- m_pRoot->MiddleOrderTraversal();
- }
-
- void Tree::LastOrderTraversal()
- {
- m_pRoot->LastOrderTraversal();
- }
main方法测试:
- #include <iostream>
- #include "Tree.h"
-
- int main(void)
- {
- Node *node1 = new Node();
- node1->index = 1;
- node1->data = 500;
-
- Node *node2 = new Node();
- node2->index = 2;
- node2->data = 800;
-
- Node *node3 = new Node();
- node3->index = 3;
- node3->data = 200;
-
- Node *node4 = new Node();
- node4->index = 4;
- node4->data = 600;
-
- Node *node5 = new Node();
- node5->index = 5;
- node5->data = 900;
-
- Node *node6 = new Node();
- node6->index = 6;
- node6->data = 700;
-
- Tree *tree = new Tree(666);
-
- tree->AddNode(0, LEFT, node1);
- tree->AddNode(0, RIGHT, node2);
-
- tree->AddNode(1, LEFT, node3);
- tree->AddNode(1, RIGHT, node4);
-
- tree->AddNode(2, LEFT, node5);
- tree->AddNode(2, RIGHT, node6);
-
- //tree->DeleteNode(6, NULL);
- //tree->DeleteNode(5, NULL);
-
- tree->DeleteNode(2, NULL);
-
- tree->PreOrderTraversal();
-
- //tree->MiddleOrderTraversal();
- //tree->LastOrderTraversal();
-
- delete tree;
-
- system("pause");
- return 0;
- }
以上就是二叉树的两种实现方,推荐使用链表的形式。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。