zoukankan      html  css  js  c++  java
  • Chapter 6(树)


    1.树的储存方式
    //****************双亲表示法************************
    #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;
    
    
    //****************孩子表示法************************
    typedef struct CTNode //孩子结点
    {
    	int child;
    	struct CTNode *next;
    }*ChildPtr;
    
    typedef struct //表头结构
    {
    	TElemType data;
    	ChildPtr firstChild;
    }CTBox;
    
    
    typedef struct 
    {
    	CTBox nodes[Max_TREE_SIZE]; //结点数组
    	int r,n;
    }CTree;
    
    
    
    //****************双亲孩子表示法************************
    
    typedef struct CTNode
    {
    	int child;
    	struct CTNode *next;
    }*ChildPtr;
    
    typedef struct
    {
    	TElemType data;
    	int parent;
    	ChildPtr firstChild;
    }CTBox;
    
    typedef struct
    {
    	CTBox nodes[Max_TREE_SIZE];
    	int r,n;
    }CTree;
    

    2.根据扩展前序列确定一个二叉树(通过外界持续输入字符串或者是以字符串的形式输入)
    //**************************BiTree.h*******************************
    #ifndef BITREE_H
    #define BITREE_H
    
    #include <stdio.h>
    #include <stdlib.h>
    
    typedef int datatype;
    
    typedef struct Tree
    {
    	datatype data;
    	struct Tree *left;
    	struct Tree *right;
    }Node,*BiTree;
    
    
    //以输入扩展前序递归的方式创建二叉树
    void CreateBiTree(BiTree *T);
    
    //后序遍历
    void NextOrderTravel(BiTree T);
    
    
    
    #endif //BITREE_H
    
    
    //**************************BiTree.c*******************************
    
    #include "BiTree.h"
    
    //以输入扩展前序递归的方式创建二叉树
    void CreateBiTree(BiTree *T)
    {
    	char ch;
    	scanf("%c",&ch);
    
    	if('#' == ch)
    	{
    		*T = NULL;
    	}
    	else
    	{
    		*T = (BiTree)malloc(sizeof(Node));
    		(*T)->data = ch;
    		CreateBiTree(&(*T)->left);
    		CreateBiTree(&(*T)->right);
    	}
    }
    
    void NextOrderTravel(BiTree T)
    {
    	if(NULL == T)return;
    
    	NextOrderTravel(T->left);
    	NextOrderTravel(T->right);
    
    	printf("%c ",T->data);
    }
    
    
    //**************************BiTreeTest.c*******************************
    #include <stdio.h>
    #include "BiTree.h"
    
    char *str;
    
    void CreateBiTreeStr(BiTree *T)
    {
    
    	char ch = *str++;
    
    	if('#' == ch)
    	{
    		*T = NULL;
    	}
    	else
    	{
    		*T = (BiTree)malloc(sizeof(Node));
    		(*T)->data = ch;
    		CreateBiTreeStr(&(*T)->left);
    		CreateBiTreeStr(&(*T)->right);
    	}
    }
    
    //将这个序列以字符串的形式输入函数生成二叉树
    void Create(BiTree *T,char *str1)
    {
    	str = str1;
    	CreateBiTreeStr(T);
    }
    
    int main()
    {
    	BiTree T = NULL;
    	CreateBiTree(&T);
    	NextOrderTravel(T);
    
    	printf("
    -------
    ");
    
    
    	char *str1 = "AB#D##C##";
    	Create(&T,str1);
    
    	NextOrderTravel(T);
    }

    3.线索二叉树的建立,线索化,遍历
    #include <stdio.h>  
    #include <stdlib.h>  
      
    typedef char ElemType;  
      
    // 线索存储标志位  
    // Link(0):表示指向左右孩子的指针  
    // Thread(1):表示指向前驱后继的线索  
    typedef enum {Link, Thread} PointerTag;  
      
    typedef struct BiThrNode  
    {  
        char data;  
        struct BiThrNode *lchild, *rchild;  
        PointerTag ltag;  
        PointerTag rtag;  
    } BiThrNode, *BiThrTree;  
      
    // 全局变量,始终指向刚刚访问过的结点  
    BiThrTree pre;  
      
    // 创建一棵二叉树,约定用户遵照前序遍历的方式输入数据  
    void CreateBiThrTree( BiThrTree *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;  
      
            CreateBiThrTree(&(*T)->lchild);  
            CreateBiThrTree(&(*T)->rchild);  
        }  
    }  
      
    // 中序遍历线索化  
    void InThreading(BiThrTree T)  
    {  
        if( T )  
        {  
            InThreading( T->lchild );        // 递归左孩子线索化  
      
            if( !T->lchild ) // 如果该结点没有左孩子,设置ltag为Thread,并把lchild指向刚刚访问的结点。  
            {  
                T->ltag = Thread;  
                T->lchild = pre;  
            }  
      
            if( !pre->rchild )  
            {  
                pre->rtag = Thread;  
                pre->rchild = T;  
            }  
      
            pre = T;  
      
            InThreading( T->rchild );        // 递归右孩子线索化  
        }  
    }  
      
    void InOrderThreading( BiThrTree *p, BiThrTree T )  
    {  
        *p = (BiThrTree)malloc(sizeof(BiThrNode));  
        (*p)->ltag = Link;  
        (*p)->rtag = Thread;  
        (*p)->rchild = *p;  
        if( !T )  
        {  
            (*p)->lchild = *p;  
        }  
        else  
        {  
            (*p)->lchild = T;  
            pre = *p;  
            InThreading(T);  
            pre->rchild = *p;  
            pre->rtag = Thread;  
            (*p)->rchild = pre;  
        }  
    }  
      
    void visit( char c )  
    {  
        printf("%c", c);  
    }  
      
    // 中序遍历二叉树,非递归  
    void InOrderTraverse( BiThrTree T )  
    {  
        BiThrTree p;  
        p = T->lchild;  
      
        while( p != T )  
        {  
            while( p->ltag == Link )  
            {  
                p = p->lchild;  
            }  
            visit(p->data);  
      
            while( p->rtag == Thread && p->rchild != T )  
            {  
                p = p->rchild;  
                visit(p->data);  
            }  
              
            p = p->rchild;  
        }  
    }  
      
    int main()  
    {  
        BiThrTree P, T = NULL;  
      
        CreateBiThrTree( &T );  
      
        InOrderThreading( &P, T );  
      
        printf("中序遍历输出结果为: ");  
      
        InOrderTraverse( P );  
      
        printf("
    ");  
      
        return 0;  
    }  

    3.赫夫曼树的建立
    #include<stdio.h>  
    #include<stdlib.h>  
    typedef int ElemType;  
    struct BTreeNode  
    {  
        ElemType data;  
        struct BTreeNode* left;  
        struct BTreeNode* right;  
    };  
      
    //1、输出二叉树,可在前序遍历的基础上修改。采用广义表格式,元素类型为int  
    void PrintBTree_int(struct BTreeNode* BT)  
    {  
        if (BT != NULL)  
        {  
            printf("%d", BT->data); //输出根结点的值  
            if (BT->left != NULL || BT->right != NULL)  
            {  
                printf("(");  
                PrintBTree_int(BT->left); //输出左子树  
                if (BT->right != NULL)  
                    printf(",");  
                PrintBTree_int(BT->right); //输出右子树  
                printf(")");  
            }  
        }  
    }  
      
    //2、根据数组 a 中 n 个权值建立一棵哈夫曼树,返回树根指针  
    struct BTreeNode* CreateHuffman(ElemType a[], int n)  
    {  
        int i, j;  
        struct BTreeNode **b, *q;  
        b = malloc(n*sizeof(struct BTreeNode));  
        for (i = 0; i < n; i++) //初始化b指针数组,使每个指针元素指向a数组中对应的元素结点  
        {  
            b[i] = malloc(sizeof(struct BTreeNode));  
            b[i]->data = a[i];  
            b[i]->left = b[i]->right = NULL;  
        }  
        for (i = 1; i < n; i++)//进行 n-1 次循环建立哈夫曼树  
        {  
            //k1表示森林中具有最小权值的树根结点的下标,k2为次最小的下标  
            int k1 = -1, k2;  
            for (j = 0; j < n; j++)//让k1初始指向森林中第一棵树,k2指向第二棵  
            {  
                if (b[j] != NULL && k1 == -1)  
                {  
                    k1 = j;  
                    continue;  
                }  
                if (b[j] != NULL)  
                {  
                    k2 = j;  
                    break;  
                }  
            }  
            for (j = k2; j < n; j++)//从当前森林中求出最小权值树和次最小  
            {  
                if (b[j] != NULL)  
                {  
                    if (b[j]->data < b[k1]->data)  
                    {  
                        k2 = k1;  
                        k1 = j;  
                    }  
                    else if (b[j]->data < b[k2]->data)  
                        k2 = j;  
                }  
            }  
            //由最小权值树和次最小权值树建立一棵新树,q指向树根结点  
            q = malloc(sizeof(struct BTreeNode));  
            q->data = b[k1]->data + b[k2]->data;  
            q->left = b[k1];  
            q->right = b[k2];  
      
            b[k1] = q;//将指向新树的指针赋给b指针数组中k1位置  
            b[k2] = NULL;//k2位置为空  
        }  
        free(b); //删除动态建立的数组b  
        return q; //返回整个哈夫曼树的树根指针  
    }  
      
    //3、求哈夫曼树的带权路径长度  
    ElemType WeightPathLength(struct BTreeNode* FBT, int len)//len初始为0  
    {  
        if (FBT == NULL) //空树返回0  
            return 0;  
        else  
        {  
            if (FBT->left == NULL && FBT->right == NULL)//访问到叶子结点  
                return FBT->data * len;  
            else //访问到非叶子结点,进行递归调用,返回左右子树的带权路径长度之和,len递增  
                return WeightPathLength(FBT->left,len+1)+WeightPathLength(FBT->right,len+1);  
        }  
    }  
      
    //4、哈夫曼编码(可以根据哈夫曼树带权路径长度的算法基础上进行修改)  
    void HuffManCoding(struct BTreeNode* FBT, int len)//len初始值为0  
    {  
        static int a[10];//定义静态数组a,保存每个叶子的编码,数组长度至少是树深度减一  
        if (FBT != NULL)//访问到叶子结点时输出其保存在数组a中的0和1序列编码  
        {  
            if (FBT->left == NULL && FBT->right == NULL)  
            {  
                int i;  
                printf("结点权值为%d的编码:", FBT->data);  
                for (i = 0; i < len; i++)  
                    printf("%d", a[i]);  
                printf("
    ");  
            }  
            else//访问到非叶子结点时分别向左右子树递归调用,并把分支上的0、1编码保存到数组a  
            {   //的对应元素中,向下深入一层时len值增1  
                a[len] = 0;  
                HuffManCoding(FBT->left, len + 1);  
                a[len] = 1;  
                HuffManCoding(FBT->right, len + 1);  
            }  
        }  
    }  
      
    //主函数  
    void main()  
    {  
        int n, i;  
        ElemType* a;  
        struct BTreeNode* fbt;  
        printf("从键盘输入待构造的哈夫曼树中带权叶子结点数n:");  
        while(1)  
        {  
            scanf("%d", &n);  
            if (n > 1)  
                break;  
            else  
                printf("重输n值:");  
        }  
        a = malloc(n*sizeof(ElemType));  
        printf("从键盘输入%d个整数作为权值:", n);  
        for (i = 0; i < n; i++)  
            scanf(" %d", &a[i]);  
        fbt = CreateHuffman(a, n);  
        printf("广义表形式的哈夫曼树:");  
        PrintBTree_int(fbt);  
        printf("
    ");  
        printf("哈夫曼树的带权路径长度:");  
        printf("%d
    ", WeightPathLength(fbt, 0));  
        printf("树中每个叶子结点的哈夫曼编码:
    ");  
        HuffManCoding(fbt, 0);  
    }  

    附件列表

  • 相关阅读:
    [LeetCode] Bulb Switcher II 灯泡开关之二
    [LeetCode] Second Minimum Node In a Binary Tree 二叉树中第二小的结点
    [LeetCode] 670. Maximum Swap 最大置换
    [LeetCode] Trim a Binary Search Tree 修剪一棵二叉搜索树
    [LeetCode] Beautiful Arrangement II 优美排列之二
    [LeetCode] Path Sum IV 二叉树的路径和之四
    [LeetCode] Non-decreasing Array 非递减数列
    [LeetCode] 663. Equal Tree Partition 划分等价树
    [LeetCode] 662. Maximum Width of Binary Tree 二叉树的最大宽度
    [LeetCode] Image Smoother 图片平滑器
  • 原文地址:https://www.cnblogs.com/LyndonMario/p/9326349.html
Copyright © 2011-2022 走看看