数据结构-树

树: 是 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_H

class 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_H

class 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.树中结点的遍历

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值