数据结构-树

来源:互联网 发布:立白皂液怎么样 知乎 编辑:程序博客网 时间:2024/06/05 11:04

树: 是 n(n≥0) 个结点的有限集合。如果该集合为空,称为空树。在任意一棵非空树中:

1)有且仅有一个特定的称为根结点 ( root ) 的结点;
2) 其他结点可分为若干个互不相交的子集(递归定义),而且每一个子集本身又是一棵树,称为根的子树。
这里写图片描述

基本概念:

结点:树的顶点;
结点的度:结点分支的个数,即子树的数目 如:A的度-3;B的度-2;K的度-0;
树的度:树中所有结点的度的最大值 如:树的度为3;
叶子结点:度为零的结点,也称终端结点 如例:K,L,F,G,M,I,J为终端结点
分支结点:度大于0的结点 如例:A,B,C,D,E
根:非终端结点
深度:结点深度:某一层结点的数目
树的深度:树有几层
森林:多棵树放在一起

二叉树

定义:所有结点的度都小于等于2

二叉树的遍历

前序遍历:根在前面访问 左根右
中序遍历:左结点 根 右结点
后序遍历:左结点 右结点 根

树的用途

搜索-人机对战、压缩软件-哈夫曼树

二叉树的表达

数组表示

父亲结点下标*2+1 该结点左
父亲结点下标*2+2 该节点右
int tree[n] 3 5 8 2 6 9 7
    3(0)
  5(1) 8(2)
2(3) 6(4) 9(5) 7(6)
Tree.h的代码如下:

#ifndef TREE_H#define TREE_Hclass Tree{public:    Tree(int size,int *pRoot); //创建树    ~Tree();        //销毁树    int *SearchNode(int nodeIndex);    //根据索引寻找结点    bool AddNode(int nodeIndex,int direction,int *pNode);  //添加结点    bool DeleteNode(int nodeIndex,int *pNode);   //删除结点    void TreeTraverse();  //遍历结点private:    int *m_pTree;    int m_iSize;};#endif

Tree.c的代码如下:

#include "Tree.h"#include <iostream>using namespace std;Tree::Tree(int size,int *pRoot){    m_pTree = new int[size];    m_iSize = size;    for(int i=0;i<size;++i)    {        m_pTree[i]=0;    }    m_pTree[0]=*pRoot;}Tree::~Tree(){    delete[] m_pTree;}int* Tree::SearchNode(int nodeIndex){    if(nodeIndex < 0 || nodeIndex >= m_iSize)    {        return NULL;    }    if(m_pTree[nodeIndex]==0)    {        return NULL;    }    return &m_pTree[nodeIndex];}bool Tree::AddNode(int nodeIndex,int direction,int *pNode){    if(nodeIndex < 0 || nodeIndex >= m_iSize)    {        return NULL;    }    if(m_pTree[nodeIndex]==0)    {        return NULL;    }    if(direction==0)    {        if(nodeIndex * 2 +1 >= m_iSize)        {            return NULL;        }        if(m_pTree[nodeIndex * 2 +1])        {            return NULL;        }        m_pTree[nodeIndex * 2 +1] = *pNode;    }    if(direction==1)    {        if(nodeIndex * 2 +2 >= m_iSize)        {            return NULL;        }        if(m_pTree[nodeIndex * 2 +2])        {            return NULL;        }        m_pTree[nodeIndex * 2 +2] = *pNode;    }    return true;}bool Tree::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 Tree::TreeTraverse(){    for(int i=0;i<m_iSize;++i)    {        cout << m_pTree[i] << " ";    }}

main.cpp的程序如下:

#include<iostream>#include"Tree.h"using namespace std;int main(){    int root = 3;    Tree *p = new Tree(10,&root);    int node1=5;    int node2=8;    p->AddNode(0,0,&node1);    p->AddNode(0,1,&node2);    int node3=2;    int node4=6;    p->AddNode(1,0,&node3);    p->AddNode(1,1,&node4);    int node5=9;    int node6=7;    p->AddNode(2,0,&node5);    p->AddNode(2,1,&node6);    int node = 0;    p->DeleteNode(5,&node);    cout << endl << "node="<< node << endl;    p->TreeTraverse();    int *p1 = p->SearchNode(2);    cout << *p1 << endl;    delete p;    while(1);    return 0;}

链表表示

要素:索引、数据、左孩子指针、右孩子指针、父结点指针
结点的数据成员如下,Node.h:

#ifndef NODE_H#define NODE_Hclass Node{public:    Node();    Node *SearchNode(int nodeIndex);    //五个数据成员    int index;  //结点的索引    int data;   //结点的数据   可以是复杂的,也可以是内    Node *pLChild;  //做孩子指针  ,都是Node*    Node *pRChild;  //右孩子指针    Node *pParent;  //父亲结点指针};#endif

Node.c文件内容如下:

#include "Node.h"#include <iostream>using namespace std;Node::Node(){    index = 0;    data = 0;    pLChild = NULL;    pRChild = NULL;    pParent = NULL;}Node *Node::SearchNode(int nodeIndex){    //判断该结点是否为要搜索的结点    if(this->index = nodeIndex)    {        return this;    }    //判断左边的结点是否为要搜索的结点    if(this->pLChild != NULL)    {        if(this->pLChild->index == nodeIndex)        {            return this->pLChild;        }    }    //判断右边的结点是否为要搜索的结点    if(this->pRChild != NULL)    {        if(this->pRChild->index == nodeIndex)        {            return this->pRChild;        }    }    return NULL;}

树的类如下Tree.h:

#ifndef TREE_H#define TREE_H#include "Node.h"class Tree{public:    Tree(); //创建树    ~Tree();        //销毁树    Node *SearchNode(int nodeIndex);    //根据索引寻找结点    bool AddNode(int nodeIndex,int direction,Node *pNode);  //添加结点    bool DeleteNode(int nodeIndex,Node *pNode);   //删除结点    //void TreeTraverse();  //遍历结点    void PreorderTraverse();  //前序遍历 根左右    void InorderTraverse();  //中序遍历   左根右    void PostorderTraverse();  //后序遍历 左右根    //结点要素:索引  数据 做孩子指针  右孩子指针(通过头结点找子结点)private:    Node *m_pRoot;};#endif

创建树的函数为Tree();
具体实现方法为:

Tree::Tree(){    m_pRoot = new Node(); //创建一个根结点}

销毁树不能只销毁一个m_pRoot指针,先看看如何实现结点的寻找,即Node *SearchNode(int nodeIndex)函数,实现如下,这里不是很理解,继续向下看

Node* Tree::SearchNode(int nodeIndex){    return m_pRoot->SearchNode(nodeIndex);//调用Node的成员函数来寻找结点}

然后是添加结点函数:bool AddNode(int nodeIndex,int direction,Node *pNode);

bool Tree::AddNode(int nodeIndex,int direction,Node *pNode){    Node *temp = this->SearchNode(nodeIndex);    if(temp == NULL)    {        return false;    }    Node *node = new Node();    //判断申请的内存是否失败    if(node == NULL)  return false;    node->index = pNode->index;    node->data = pNode->data;    if(direction == 0)    {        temp->pLChild = node;    }    if(direction == 1)    {        temp->pRChild = node;    }    return true;}

对于删除结点的函数设计比较困难,函数为bool DeleteNode(int nodeIndex,Node *pNode); //删除结点
需要在Node中添加void DeleteNode()函数:

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 != NULL)        {            this->pParent->pLChild = NULL;        }        if(this->pParent->pRChild != NULL)        {            this->pParent->pRChild = NULL;        }    }    delete this;}

课程要求

完成树的基本操作:
1.树的创建与销毁;
2.树中结点的搜索;
3.树中结点的添加与删除;
4.树中结点的遍历

原创粉丝点击