数据结构之树操作

简介: 数据结构之树操作


    本文打出了大部分树的操作 和部分知识点   还有自己编写的哈夫曼树中的select函数(看书上是直接调用便自己打出了自己理解的select函数,有错请在评论区指出)

后续会补充栈,队列,线性表操作总结。

       //二叉树树的存储结构
typedef struct BeTnode{
  char data;
  struct BeTnode*left,*right;
}BeTnode,*BeTree;    
      //        建立先序二叉树   要正好返回 
    BeTree jianlierchashu (BeTree t)
    {
      char ch;
      scanf("%c",&ch);
      if(ch=='#')
      {
        return ;
      }
      if(ch!='#')
      {
        t=(BeTree) malloc (sizeof(BeTnode));
        t->data=ch;
        t->left=NULL;
        t->right=NULL;
        jianlierchashu(t->left);
        jianlierchashu(t->right);
        return t;
      } 
    }
     //     求二叉树叶子节点的个数
int yezijiediangeshu(BeTree t)
{
  if(t==NULL)
  {
    return 0;
  }
  if(t->left==NULL&&t->right==NULL)
  {
    return 1;
  }
  int n=0,m=0;
  n=yezijiediangeshu(t->left);
  m=yezijiediangeshu(t->right);
  return m+n ;
     }     
//          求二叉树节点个数
int  jiediangeshu(BeTree t) 
{
        if(t==NULL)
        {
          return 0;
    }
    int n=0,m=0;
  n=jiediangeshu(t->left);//0 1
  m=jiediangeshu(t->right);//0 
  return 1+n+m;//1
}
              //二叉树树的深度
int shendu(BeTree t)
{
  if(t==NULL)
  return 0;
  int n=0,m=0;
  n=shendu(t->left);    
  m=shendu(t->right);
  return n>m?n+1:m+1; 
} 
//      中序线索二叉树 
/*
       主要是添加两个标识域
ltage=    1-则左指针域前驱       0-则左指针域左孩子     
rtage=    1-则右指针域后驱       0-则右指针域右孩子 
              物理存储结构 
*/ 
typedef struct TNode{
  char data;
  struct TNode *left;
  struct TNode *right;
  int ltage;
  int rtage;
}TNode,*BTNode; 
    void xiansuoerchashu(BTNode t)
  {
    BTNode pro=NULL;
    if(t)
    {
    xiansuoerchashu(t->left);  //因为为中序所以  要从左开始  递归调用到最左   返回
    if(t->left==NULL)
    {
    t->ltage=1;//设置标记 
    t->left=pro;  //pro为前驱    全局变量    初始值为NULL 
    } 
       else
     t->ltage=0;
     if(pro->right==NULL)    //这里为什么是pro那?因为现在操作的是t   只有t和pro的地址   所以要填充pro的右指针域 
     {
      pro->rtage=1;
      pro->right=t;
      }
      else
      pro->rtage=0; 
      pro=p;       //因为当前节点的操作完成了   所以将其赋值    递归右子树 
      xiansuoerchashu(t->right);
    }
   } 
      //树的存储 -1   双亲表示法 
  typedef struct PTNode{
    char data;
    int parent;//  双亲位置域 
  }PTNode;      //节点
  //树结构
  # define MAXSIZE 100
  typedef struct {
    PTNode node[MAXSIZE];//创建数组   可以存放MAXSIZE个节点     
    int r,n; //根节点位置个数 
  }PTree;    
    //树的存储 -2  孩子表示法    
  //孩子节点结构的定义  
typedef struct CTNode{
  int child;  //    int 类型    为该孩子在数组中的下标 
  struct CTNode* nexthaizi;        // 双亲节点的下一个孩子 
}*childptr;    
    //双亲节点结构
  typedef struct     
     {
      char data;
      childptr firstchild;      //孩子链表的头指针 
     }CTBox;
  //树结构
  typedef struct {
      CTBox node[MAXSIZE];
      int r,n;     //根节点的位置和节点数 
  }CTree;
   //方便找孩子  不方便找双亲    则添加一个双亲节点 
  typedef struct     
     {
      char data;
      int   pro; 
      childptr firstchild;      //孩子链表的头指针 
     }CTBox;
     //带双亲的孩子链表 
     //树的存储 -3   二叉链表表示法    
     /*
     左指针域    ---第一个孩子结点
     右指针域    ---向右一个  兄弟结点 
     找双亲比较困难 
     */
     typedef struct CTNode{
      char data;
      struct CTNode * lefthaizi;
        struct CTNode *rightxdi; 
     }CTNode;
     //哈夫曼树
      // 结点结构     
  typedef struct Hafuman  //顺序存储  ---     1维结构数组 
  {
    //权值
    //双亲  左孩子右孩子下标
    int weight;
    int parent,left,right; 
   }Hafuman,*THafuman; //---是动态数组存储一个哈夫曼树
    //建立哈夫曼树(最优二叉树)   
    /*
  权值越大越靠近根
  所以找权值要从小到大  从下到上进行构造哈夫曼树 
  每个权值都是根    权值实际也是叶子节点 
  而且不唯一,因为没有限定左右子树,并且有权值重复时,可能树的高度都不唯一,唯一的只是带权路径长度之和最小。
          王卓老师的口诀 
   构造森林全是根   选用二小造新树
   删除二小添新人   重复2,3剩单根 
  */
   void creatHfm(THafuman t,int n)    //   t是哈夫曼树      n是 有权值的个数(叶子节点)    需要合并n-1次   
   {
    if(n<=1)
     return ;
/*
1.    建数组 for循环初始化  3个域均为0 
2.    选出无双亲 中权值最小的两个  组成新的二叉树
3.    组成后    权值最小的两个  消失(有双亲) 
*/      
    int m=2*n-1;
    t=(THafuman) malloc(sizeof(Hafuman)*(1+m)); //从1开始使用
    for(int i=1;i<m+1;i++)
  {
    t[i].left=0;
    t[i].parent=0;
    t[i].right=0;
  }   
  for(int i=1;i<n+1;i++)
  {
    scanf("%d",&t[i].weight);
  }    
    //-----------------------------------------------------------
  //因为要 选出无双亲 中权值最小的两个  组成新的二叉树   所以要自定义函数胡
 int s1,s2;
  for(i=n+1;i<m+1;i++)
  {
     select(t,&s1,&s2,i);  
        t[i].weight=s1+s2;
  t[i].right=s1;
  t[i].left=s2;        
  }   
  } 
  int cmp(int *x, int *y) {
    return *x - *y;
}
  void select(THafuman *t,int &s1,int &s2,int n)    //s1,s2是需要返回的值 
  {
    int m=sizeof(t)/sizeof(Hafuman);
    THafuman a[m];//指针数组 
    int j=0;
  for(int i=1;i<m;i++)
  {
  if(t[i].parent==0)
  {
   a[j]=t[i]; 
    j++;
  }
  }   int i=0;
    qsort(a,j,sizeof(Hafuman),cmp);
    for(i=0;i<m;i++)
    { int p=0;
         if(a[0]==t[i]||a[1]==t[i])
       {
                  p++;
            t[i].parent=n;
            if(p==1)
        *s1=i;  
            else
            *s2=i;
       }  
  }
      }      
//哈夫曼编码
//算概率大  则权大  则要靠近根
//左分支标记为0,右分支标记为1进行编码  
/*
从根到叶子进行编码 
*/     


相关文章
|
5天前
|
算法 Java
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
28 3
 算法系列之数据结构-Huffman树
|
4月前
|
算法
数据结构之博弈树搜索(深度优先搜索)
本文介绍了使用深度优先搜索(DFS)算法在二叉树中执行遍历及构建链表的过程。首先定义了二叉树节点`TreeNode`和链表节点`ListNode`的结构体。通过递归函数`dfs`实现了二叉树的深度优先遍历,按预序(根、左、右)输出节点值。接着,通过`buildLinkedList`函数根据DFS遍历的顺序构建了一个单链表,展示了如何将树结构转换为线性结构。最后,讨论了此算法的优点,如实现简单和内存效率高,同时也指出了潜在的内存管理问题,并分析了算法的时间复杂度。
83 0
|
2月前
|
存储 C++
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
【数据结构——树】哈夫曼树(头歌实践教学平台习题)【合集】目录 任务描述 相关知识 测试说明 我的通关代码: 测试结果:任务描述 本关任务:编写一个程序构建哈夫曼树和生成哈夫曼编码。 相关知识 为了完成本关任务,你需要掌握: 1.如何构建哈夫曼树, 2.如何生成哈夫曼编码。 测试说明 平台会对你编写的代码进行测试: 测试输入: 1192677541518462450242195190181174157138124123 (用户分别输入所列单词的频度) 预
72 14
【C++数据结构——树】哈夫曼树(头歌实践教学平台习题) 【合集】
|
2月前
|
Java C++
【C++数据结构——树】二叉树的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现二叉树的基本运算。​ 相关知识 创建二叉树 销毁二叉树 查找结点 求二叉树的高度 输出二叉树 //二叉树节点结构体定义 structTreeNode{ intval; TreeNode*left; TreeNode*right; TreeNode(intx):val(x),left(NULL),right(NULL){} }; 创建二叉树 //创建二叉树函数(简单示例,手动构建) TreeNode*create
61 12
|
2月前
|
C++
【C++数据结构——树】二叉树的性质(头歌实践教学平台习题)【合集】
本文档介绍了如何根据二叉树的括号表示串创建二叉树,并计算其结点个数、叶子结点个数、某结点的层次和二叉树的宽度。主要内容包括: 1. **定义二叉树节点结构体**:定义了包含节点值、左子节点指针和右子节点指针的结构体。 2. **实现构建二叉树的函数**:通过解析括号表示串,递归地构建二叉树的各个节点及其子树。 3. **使用示例**:展示了如何调用 `buildTree` 函数构建二叉树并进行简单验证。 4. **计算二叉树属性**: - 计算二叉树节点个数。 - 计算二叉树叶子节点个数。 - 计算某节点的层次。 - 计算二叉树的宽度。 最后,提供了测试说明及通关代
60 10
|
2月前
|
存储 算法 测试技术
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
本任务旨在实现二叉树的遍历,包括先序、中序、后序和层次遍历。首先介绍了二叉树的基本概念与结构定义,并通过C++代码示例展示了如何定义二叉树节点及构建二叉树。接着详细讲解了四种遍历方法的递归实现逻辑,以及层次遍历中队列的应用。最后提供了测试用例和预期输出,确保代码正确性。通过这些内容,帮助读者理解并掌握二叉树遍历的核心思想与实现技巧。
60 2
|
5月前
|
存储 算法 搜索推荐
探索常见数据结构:数组、链表、栈、队列、树和图
探索常见数据结构:数组、链表、栈、队列、树和图
165 64
|
4月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
107 5
|
4月前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
173 16
|
4月前
|
算法
数据结构之文件系统模拟(树数据结构)
本文介绍了文件系统模拟及其核心概念,包括树状数据结构、节点结构、文件系统类和相关操作。通过构建虚拟环境,模拟文件的创建、删除、移动、搜索等操作,展示了文件系统的基本功能和性能。代码示例演示了这些操作的具体实现,包括文件和目录的创建、移动和删除。文章还讨论了该算法的优势和局限性,如灵活性高但节点移除效率低等问题。
99 0