数据结构之树操作

     本文打出了大部分树的操作 和部分知识点   还有自己编写的哈夫曼树中的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进行编码	 
/*
从根到叶子进行编码 
*/		 
		 
		 
		 
		 
		 
		 
		 
		 
		 
		 
		 

                                          本篇文章主要是树的操作

  • 20
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论
一、实验目的: 理解二叉特别是完全二叉的性质,掌握二叉的存储结构(二叉链表);熟练掌握二叉的常用操作算法(初始化、插入结点、删除结点、遍历等);初步掌握二叉的应用。 二、实验内容: 要求采用二叉链表作为存储结构,完成二叉的建立,前序、中序和后序遍历的操作,求所有叶子及结点总数的操作等。 具体要求如下: ①给出基于二叉链表的二叉类的定义; ②给出二叉初始化(构造函数)的实现; ③给出二叉三种遍历算法的递归实现; ④二叉先序遍历的非递归算法实现; ⑤利用二叉的遍历算法求二叉的结点数、二叉的叶结点数、二叉的高度; ⑥二叉的撤销删除 三、实验步骤: 1、需求分析: 本演示程序用JAVA编写,完成的生成,任意位置的插入、删除,以及遍历二叉中的结点,查找和修改中元素的值。 ① 输入的形式和输入值的范围:插入元素时需要输入插入的位置和元素的值;删除元素时输入删除元素的位置;遍历时采用三种遍历方法中的一种遍历方法;修改操作时需要输入的元素的值;查找操作时,需要找到要查找元素的位置。在所有输入中,元素的值都是整数。 ② 输出的形式:在所有四种操作中都显示操作是否正确以及操作中的内容。其中删除操作后显示删除的元素的值,遍历二叉中的元素,查找操作、修改操作后显示修改的值。 ③ 程序所能达到的功能:完成的生成(通过插入操作)、插入、删除、遍历、查找、修改操作。 ④ 测试数据: A. 中已有以50,25,75,12,37,43,30,33,87,93,97为关键字的结点 B. 插入操作中依次输入10,20,30,40,50,60,70,80,90,100十个数 C. 删除操作中输入10删除值为10的元素 D. 查找操作中输入20,30,40,50返回这个元素在中的位置 2.概要设计: 1)为了实现上述程序功能,需要定义的抽象数据类型: public int iData; public double dData; public Node leftChild; public Node rightChild; private Node root;int value; private Node getSuccessor; 基本操作:{ Tree () 操作结果:构造一个空的二叉 insert () 初始条件:是否存在一个空二叉 操作结果:往二叉中插入数值 delete () 初始条件:存在一非空的二叉 操作条件:将二叉中的元素删除 displayTree () 初始条件:存在一非空的 操作条件:显示非空中的所有元素的值 getString () 初始条件:存在一非空的二叉 操作结果:返回整个字符串的数值 getChar () 初始条件:存在一非空的二叉 操作结果:返回字符型的数值 getInt () 初始条件:存在一非空的二叉 操作结果:返回整型的数值 find () 初始条件:存在一非空二叉 操作结果:从二叉中查找某一元素 traverse () 初始条件:存在一非空的二叉 操作结果:对二叉中的元素进行遍历 preorder () 初始条件:存在一非空的二叉 操作结果:对二叉中的元素进行先根遍历 inOrder () 初始条件:存在一非空的二叉 操作结果:对二叉中的元素进行中根遍历 postOrder () 初始条件:存在一非空的二叉 操作结果:对二叉中的元素进行后根遍历 DisplayNode () 初始条件:存在一非空的二叉 操作结果:显示出二叉中的整形数值和双精度浮点型数值 public static void main 操作结果:调用主函数

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小唐同学爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值