《大话数据结构》第六章.树。2018-7-27-2018-2

第六章 树

概念:

根结点是唯一的。

度:结点拥有的子树数(只是一层,根结点并不是最大的)。度为0叫做叶结点。度不为0的结点称为非终端结点或分支结点。树的度是树内各节点的最大值。

深度、高度:有多少层。

线性表与树:

线性表:第一个数据元素:无前驱。    最后一个数据元素:无后继           中间元素:一个前驱一个后继

树:根结点:无双亲。                         叶结点:无孩子,可以多个          中间结点:一个双亲多个孩子

树的存储结构之双亲表示法:

双亲只是一个,并不是两个。

除了根结点外,可能没有孩子,但一定有双亲。以一组连续空间存储树的结点,每个结点,都有一个指示器,存双亲结点的位置。

 data  parents

其中data是数据域,存储结点的数据信息。而parents是指针域,存储该结点的双亲在数组中下标。代码:

#define MAX_TREE_SIZE 100

typedef int TElemType;   /*树结点的数据类型,目前暂定义为整型*/

typedef struct PTNode   /*结点结构*/

{
    TElemType data;
    int parent;
}PTNode;

typedef struct         /*树结构*/
{
   PTNode nodes[MAX_TREE_SIZE]; /*结点数组*/
   int r,n;          /*根的位置和结点*/
}PTREE;

根节点没有双亲。所以根节点位置parents设为-1。

孩子表示法:把每个孩子结点排列起来,以单链表作存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空,n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组。

双亲孩子表示法:在上面的在加上双亲的位置。

两种结点结构:

孩子链表结点:child数据域但存储的是下标,next指针域,指向下一个孩子。

#define MAX_TREE_SIZE 100

//孩子结点
typedef struct CTNode
{
  int child;   //孩子结点下标
  struct CTNode *next;    //指向下一个孩子结点的指针
}*ChildPtr

data是数据域,存储某结点的数据信息。firstchild是头指针域,存储该节点的孩子链表的头指针。中间还要加个parents。

//表头结构
typedef char ElemType; 
typedef struct
{
    ElemType data;//存放在树中结点的数据
    int parent;    //存放双亲下标
    ChildPtr firstchild;//指向第一个孩子的指针
}CTBox;
//树结构
typedef struct
{
    CTBoxnodes[MAX_TREE_SIZE];//结点数组
    int r,n;
}

二叉树的定义

下面没有三个叉就是二叉树,最多是两个就行。左和右不一样。

斜树:全部往左斜和全部往右斜。

满二叉树:叶子在一层,都有左右子树。

完全二叉树:对一棵具有 n 个结点的二叉树按层序编号,如果编号为 i (l<:i<n) 的结点与同 样深度的满二叉树中编号为 i 的结点在二叉树中位置完全相同,则这棵二叉树称为完 全二叉树。(从左到右的,最多差一层)满一定是完全。

二叉树的性质

二叉树第i层上至多有2^(i-1)个结点。(满二叉)

深度为k的二叉树至多有2^k-1个结点。

后面性质不看了,又不是要考研。

二叉树的存储结构

二叉树的顺序存储结构:用一维数组。

二叉链表:

一个数据域和两个指针域。

/*二叉树的二支键-*-结点结构定义*/
typedef struct BiTNode    /*结点结构*/
{
    TElemType data;  /*结点数据*/
    strcut BiTNode *lchild,*rchild; /*左右孩子指针*/
}BiTNode, *BLTree;

遍历:https://blog.csdn.net/qiki_tangmingwei/article/details/79325611

1.前序遍历。先根、左、右。

一个tree只有一个lchild一个data一个rchild。

2.中。左、根、右。

3.后。先叶子后结点。左、右、根。

4.层。一层一层。

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define MAXSIZE 100;
/*二叉树的二叉链表结点结构定义"*/
typedef struct BiTNode
{
    char data;
    struct BiTreeNode *left;
    struct BiTreeNode *right;
}BiTreeNode,*BiTree;

/**二叉树的建立--按照先序方式建立--插入**/
void CreateBiTree(BiTree *T)
{
    char val;
    scanf("%c",&val);
 
    if(val == '#')
        *T = NULL;  //null表示为空枝
 
    else
    {
        *T = (BiTree)malloc(sizeof(BiTreeNode));  //BiTReee=BiTNode *
        (*T)->data = val;
        CreateBiTree(&(*T)->left);
        CreateBiTree(&(*T)->right);
    }
}
/**先序遍历  根左右**/
void PreOrderTravel(BiTree T)
{
    if(T==NULL)
        return;
    printf("%c ",T->data);
    PreOrderTravel(T->left);
    PreOrderTravel(T->right);
}
 
/**中序遍历 左根右**/
void InOrderTravel(BiTree T)
{
    if(T==NULL)
        return;
    InOrderTravel(T->left);
    printf("%c ",T->data);
    InOrderTravel(T->right);
}
 
/**后序遍历 左右根**/
void TailOrderTravel(BiTree T)
{
    if(T==NULL)
        return;
    TailOrderTravel(T->left);
    TailOrderTravel(T->right);
    printf("%c ",T->data);
}
int main()
{
 
    printf("测试代码\n");
    BiTree T;
    T = (BiTree)malloc(sizeof(BiTreeNode));
 
    printf("请给二叉树按照先序方式依次输入结点的值(空结点为#):\n");
    CreateBiTree(&T);
 
 
    printf("先序方式遍历结果:\n");
    PreOrderTravel(T);
    printf("\n");
 
    printf("中序方式遍历结果:\n");
    InOrderTravel(T);
    printf("\n");
 
    printf("后序方式遍历结果:\n");
    TailOrderTravel(T);
    printf("\n");
    return 0;
}

typedef有取别名的作用,所以BitNode的意思是struct BitNode{...),BiTree的意思是struct BitNode{...)*。

BiTree &T 是取指针地址的意思,如同int  &a,取a得地址一样。

BitNode *T  和  BiTree T 是定义结构指针变量。

线索二叉树:

上述有许多的NULL,造成资源浪费。

线索:指向前驱和后续结点。加上线索的二叉链表称为线索链衰,相应的二叉树就.称为线索二叉树

ltag是0时,指向该结点的左孩子,为1时指向前驱。

rtag是0时,指向该节点的右孩子,为1时指向后继。

#include <stdio.h>
#include <stdlib.h>

typedef char ElemType;

typedef enum {link,thread}PointerNag;//link=0 ,thread=1

typedef struct BiThrNode
{
    char data;
    struct BiThrNode *lchild,*rchild;
    PointerNag ltag,rtag;
}BiThrNode,*BiThrTree;
//全局变量。始终指向刚刚访问过的结点
BiThree pre;
//创建一个二叉树
void createtree(BiThrNode *T)
{
    char c;
    scanf("%c",c);
    if(' '==c)
    {
        *T=NULL;
    }
    else
    {
        *T=(BiThrNode)malloc(sizeof(BiThrNode));
        (*T)->data=c;
        (*T)->ltag=link;
        (*T)->rtag=link;
        createtree(&(*T)->lchild);
        createtree(&(*T)->rchild);
    }    
}

//中序遍历线索话
void InThreading(BiThrNode *T)
{
    if( T )
    {
        InThreading(T->lchild);  //递归左孩子
        if(!T->lchild)             //如果该结点没有左孩子,设置ltag为thread,并把lchid指向上一个访                     问的结点(前驱)
        {
            T->ltag=thread;
            T->lchild=pre;
        }
        if(!pre)            //后继还不知道,只能把上一个结点的后一个设为当前的。
        {
            pre->rtag=thread;
            pre->rchild=T;
        }
        pre=T;
        InThreading(T->rchild);
    }
}


设置一个头结点,头结点左链lchild指向根节点1,头结点右链rchil向中序遍历的最后一个结点的后继2。

二叉树的中序遍历的第一个结点lchild指向头结点3,最后一个结点指向头结点4.

/* T 指向头结点.头结点在左链lchild 指向根结点,头结点右链 rchild 指向中序遍历的最后一个结点。 中序遍历二又线索链表表示的二又树 T */ 

int InorderTrading(BiThrTree *P, BiThrTree t)
{
    *P = (BiThrTree)malloc(sizeof(BiThrNode));
    (*P)->ltag=link;
    (*P)->rtag=thread;
    if(!T)                   //空树指向本身
    {
        (*p)->lchild=p;
    }
    else                    //不是空树
    {
        (*P)->lchild=*T;
        pre = *P;
        InThreading(T);
        pre->rchild=*P;
        pre->rtag=thread;
        (*P)->rchild=pre;
    }
}

没有仔细看,哪天心情好在仔细看一看。

荷夫曼编码

创建一个优先级队列。

按次数、权重,从小到大排列。

创建一个树。

最小的两个构成新结点。

左边是0,右边是1.

然后,encode、decode。

代码太多了,小甲鱼讲了,但是45分钟不想看了,看下一章吧。
 

猜你喜欢

转载自blog.csdn.net/weixin_41982696/article/details/81225899