树的存储结构&树和森林的遍历

树的存储结构

(1)双亲表示法(顺序存储)

每个结点中保存指向双亲的“指针”

# define maxsize 100  //树中最多结点数
typedef struct {      //树中结点定义
    int data;         //数据元素
    int parent;       //双亲位置域
}ptnode;
typedef struct {      //数的类型定义
    ptnode nodes[maxsize];//双亲表示
    int n;            //结点数
}ptree;

增加新元素只需保存该结点的值,并且保存他和双亲的关系即可

删除结点可以把双亲指针设为-1,也可以把尾部的数据移上来(这样保证前边的存储单元都是有效的),删除节点要将节点数减一

二叉树的顺序存储:一定要把二叉树的结点编号与完全二叉树对应起来

(2)孩子表示法(顺序+链式存储)

每个结点中除了要保存该结点的数据外,还要保存指向它第一个孩子的指针

struct ctnode {
    int child;           //孩子结点在数组中的位置
    struct ctnode* next; //下一个孩子
};
typedef struct {
    int data;
    struct ctnode* firstchild; //第一个孩子
}ctbox;
typedef struct {
    ctbox nodes[maxsize];
    int n, r;           //结点数和根的位置
}ctree;

(3)孩子兄弟表示法(链式存储)

typedef struct csnode {
    int data;                                    //数据域
    struct csnode* firstchild, * nectsibling;    //第一个孩子和右兄弟指针
}csnode,*cstree;

左指针指向第一个孩子结点,右指针指向一个结点的后面一个兄弟结点(根结点的右指针肯定为空)

(4)  森林和二叉树的转换

树的存储结构&树和森林的遍历_第1张图片

 树的存储结构&树和森林的遍历_第2张图片

 树和森林的遍历

(1)树的遍历

1.先根遍历:若树非空,先访问根结点,再依次对每颗子树进行先根遍历

void preorder(treenode* r) {
    if (r != NULL) {
        visit(r);     //访问根结点
        while (r还有下一个子树t)
            preorder(t);    //先根遍历下一颗子树
    }
}

 2.后根遍历:若树非空,先依次对每颗子树进行后根遍历,最后再访问根结点

void postorder(treenode* r) {
    if (r != NULL) {
        while (r还有下一个子树)
            postorder(t);      //后根遍历下一棵子树
        visit(r);              //访问根节点
    }
}

3.树的层次遍历:(队列实现)

(1)若树非空,则根结点入队,

(2)若队列非空,队头元素出队并访问,同时将该元素的孩子依次入队

(3)重复(2)直到队列为空

(2)森林的遍历

1.森林的先序遍历 :若森林为非空,则按如下规则进行遍历:

访问森林中第一课树的根结点

先序遍历第一棵树中根结点的子树森林

先序遍历除去第一棵树之后剩余的树构成的森林

2.森林的中序遍历:若森林为非空,则按如下规则进行遍历:

中序遍历森林中第一棵树的根结点的子树森林

访问第一棵树的根结点

中序遍历除去第一棵树之后剩余的树构成的森林

你可能感兴趣的:(java,算法,数据结构)