`

每周一道数据结构(三)树、二叉树、最优二叉树

阅读更多
原帖地址:http://www.cnblogs.com/coder2012/archive/2013/06/05/3102868.html




 


  树形结构是一类非常重要的非线性结构,它可以很好地描述客观世界中广泛存在的具有分支关系或层次特性的对象,因此在计算机领域里有着广泛应用,如操作系统中的文件管理、编译程序中的语法结构和数据库系统信息组织形式等。



 


树的相关定义




  1. 节点的度:一个节点含有的子树的个数称为该节点的度;

  2. 树的度:一棵树中,最大的节点的度称为树的度;

  3. 叶节点终端节点:度为零的节点;

  4. 非终端节点分支节点:度不为零的节点;

  5. 双亲节点父节点:若一个结点含有子节点,则这个节点称为其子节点的父节点;

  6. 孩子节点子节点:一个节点含有的子树的根节点称为该节点的子节点;

  7. 兄弟节点:具有相同父节点的节点互称为兄弟节点;

  8. 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;

  9. 树的高度深度:树中节点的最大层次;

  10. 堂兄弟节点:双亲在同一层的节点互为堂兄弟;

  11. 节点的祖先:从根到该节点所经分支上的所有节点;

  12. 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。

  13. 森林:由m(m>=0)棵互不相交的树的集合称为森林;


 


二叉树




  二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。


  二叉树(BinaryTree)是n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的、分别称作这个根的左子树右子树的二叉树组成。


  完全二叉树:对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树。


1.二叉树的遍历


   所谓遍历二叉树,就是遵从某种次序,访问二叉树中的所有结点,使得每个结点仅被访问一次。


  二叉树的遍历包括三种:



  • DLR称为前根遍历(前序遍历)

    •   访问结点的操作发生在遍历其左右子树之前



  • LDR称为中根遍历(中序遍历)

    •   访问结点的操作发生在遍历其左右子树之中(间)



  • LRD称为后根遍历(后序遍历)


    •   访问结点的操作发生在遍历其左右子树之后



递归实现:



void preorder(NODE *p)
{
if(p!=NULL)
{printf(“
%d ”,p->data);
preorder(p
->lchild);
preorder (p
->rchild);}
}

void InOrder(BinTree T)
{
if(T) { // 如果二叉树非空
InOrder(T->lchild);
printf(
"%c",T->data); // 访问结点
InOrder(T->rchild);
}
}
// InOrder

void posorder(NODE *p)
{
if(p!=NULL)
{
posorder(p
->lchild);
posorder (p
->rchild);
printf(“
%d ”,p->data);
}


非递归实现:



/*算法思想:

利用队列基本操作
1.初始化:根结点入队列
2.while(队列非空)
{
a.队首元素出队列
b.原队首元素对应的左、右孩子(非空)入队列
}
*/

void traverse(NODE *T)
{
NODE
*q[100];
int head,tail, i;
q[
0]=T;head=0;tail=1;
while(head<tail)
{
p
=q[head++];
printf(“
%c”,T->data);
if(p->lchild!=NULL)
q[tail
++]=p->lchild;
if(p->rchild!=NULL)
q[tail
++]=p->rchild;
}
}


 


2.二叉树的构造


  基于先序遍历的构造,即以二叉树的先序序列为输入构造。



void CreateBinTree (BinTree *T)
{
char ch;
if((ch=getchar())=='')
*T=NULL; //读人空格,将相应指针置空
else{ //读人非空格
*T=(BinTNode *)malloc(sizeof(BinTNode)); //生成结点
(*T)->data=ch;
CreateBinTree(
&(*T)->lchild); //构造左子树
CreateBinTree(&(*T)->rchild); //构造右子树
}
}


 


最优二叉树




    在权为wl,w2,…,wn的n个叶子所构成的所有二叉树中,带权路径长度最小(即代价最小)的二叉树称为最优二叉树哈夫曼树


  假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:


  1.  将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);

  2.  在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;

  3. 从森林中删除选取的两棵树,并将新树加入森林;

  4. 重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。



  具体代码:



#include "stdio.h"
#include
"stdlib.h"
#define m 100

struct ptree //定义二叉树结点类型
{
int w; //定义结点权值
struct ptree *lchild; //定义左子结点指针
struct ptree *rchild; //定义右子结点指针
};

struct pforest //定义链表结点类型
{
struct pforest *link;
struct ptree *root;
};

int WPL=0; //初始化WTL为0
struct ptree *hafm();
void travel();
struct pforest *inforest(struct pforest *f,struct ptree *t);

void travel(struct ptree *head,int n)
{
//为验证harfm算法的正确性进行的遍历
struct ptree *p;
p
=head;
if(p!=NULL)
{
if((p->lchild)==NULL && (p->rchild)==NULL) //如果是叶子结点
{
printf(
"%d ",p->w);
printf(
"the hops of the node is: %d/n",n);
WPL
=WPL+n*(p->w); //计算权值
}//if
travel(p->lchild,n+1);
travel(p
->rchild,n+1);
}
//if
}//travel

struct ptree *hafm(int n, int w[m])
{
struct pforest *p1,*p2,*f;
struct ptree *ti,*t,*t1,*t2;
int i;
f
=(pforest *)malloc(sizeof(pforest));
f
->link=NULL;
for(i=1;i<=n;i++) //产生n棵只有根结点的二叉树
{
ti
=(ptree*)malloc(sizeof(ptree));//开辟新的结点空间
ti->w=w[i]; //给结点赋权值
ti->lchild=NULL;
ti
->rchild=NULL;
f
=inforest(f, ti);
//按权值从小到大的顺序将结点从上到下地挂在一颗树上
}//for
while(((f->link)->link)!=NULL)//至少有二棵二叉树
{
p1
=f->link;
p2
=p1->link;
f
->link=p2->link; //取出前两棵树
t1=p1->root;
t2
=p2->root;
free(p1);
//释放p1
free(p2); //释放p2
t=(ptree *)malloc(sizeof(ptree));//开辟新的结点空间
t->w = (t1->w)+(t2->w); //权相加
t->lchild=t1;
t
->rchild=t2; //产生新二叉树
f=inforest(f,t); //每次构造一颗二叉树的时候,都要从新排列一下
}
//while
p1=f->link;
t
=p1->root;
free(f);
return(t); //返回t
}

pforest
*inforest(struct pforest *f,struct ptree *t)
{
//按权值从小到大的顺序将结点从上到下地挂在一颗树上
struct pforest *p, *q, *r;
struct ptree *ti;
r
=(pforest *)malloc(sizeof(pforest)); //开辟新的结点空间
r->root=t;
q
=f;
p
=f->link;
while (p!=NULL) //寻找插入位置
{
ti
=p->root;
if(t->w > ti->w) //如果t的权值大于ti的权值
{
q
=p;
p
=p->link; //p向后寻找
}//if
else
p
=NULL; //强迫退出循环
}//while
r->link=q->link;
q
->link=r; //r接在q的后面
return(f); //返回f
}

void InPut(int &n,int w[m])
{
printf(
"please input the sum of node/n"); //提示输入结点数
scanf("%d",&n); //输入结点数
printf ("please input weight of every node/n"); //提示输入每个结点的权值
for(int i=1;i<=n;i++)
scanf(
"%d",&w[i]); //输入每个结点权值
}

int main( )
{
struct ptree *head;
int n,w[m];
InPut(n,w);
head
=hafm(n,w);
travel(head,
0);
printf(
"The length of the best path is WPL=%d", WPL);//输出最佳路径权值之和
return 1;
}


  

本文链接

分享到:
评论

相关推荐

    数据结构--二叉树--思维导图.pdf

    二叉树是一种常见的数据结构,它是一种树形结构,每个节点最多有两个孩子节点,分别是左子树和右子树。二叉树可以用来存储大量数据,并且可以快速地查找、插入和删除数据。 二叉树的定义:二叉树是由节点组成的树形...

    数据结构 树和二叉树ppt教程

    【数据结构:树和二叉树】 树是一种非线性的数据结构,它的基本概念和术语在计算机科学中至关重要,尤其在算法设计和数据组织中扮演着核心角色。树的定义基于递归,一棵非空树包含一个根节点,以及一组互不相交的...

    构造二叉树 最优二叉树 树 输出二叉树到屏幕 C# .net

    最优二叉树,也称为哈夫曼树,是一种带权重的二叉树,用于数据编码以提高空间效率。它的构建目标是最小化所有路径的长度总和。哈夫曼树的构建通常采用贪心策略,通过合并权重最小的两个节点来逐步构造树。C#中,...

    数据结构之树二叉树必看

    在深入探讨之前,我们先理解一下二叉树的基本定义:二叉树是一种特殊的树形数据结构,其中每个节点最多有两个子节点,通常称为左子节点和右子节点。这种结构使得二叉树在处理分叉决策或层次关系时非常有效。 二叉树...

    最优二叉树 c++ 数据结构

    最优二叉树,又称为哈夫曼树或最小带权路径长度树,是一种特殊的二叉树,主要用于数据编码,特别是数据压缩。在最优二叉树中,每个叶子节点都代表一个待编码的字符,而其权重是该字符在数据源中的出现频率。非叶子...

    C++(数据结构):树和二叉树

    C++(数据结构):树和二叉树 C++(数据结构):树和二叉树 C++(数据结构):树和二叉树 C++(数据结构):树和二叉树 C++(数据结构):树和二叉树 C++(数据结构):树和二叉树 C++(数据结构):树和二叉树 C++(数据结构):树...

    东北大学数据结构实验3 树和二叉树

    ### 东北大学数据结构实验3:树和二叉树 #### 实验背景 本次实验是针对东北大学计算机专业本科生的数据结构课程中的一项实践任务。实验的主要目的是帮助学生深入理解和掌握树形数据结构中的两种基本类型——树...

    数据结构树与二叉树算法汇总

    根据给定的信息,本文将对数据结构中的树与二叉树相关的算法进行详细的解析与总结。主要内容包括:如何使用二叉树表示算术表达式、二叉树的顺序存储结构及其中叶子节点的计算方法、以及如何递归地构建二叉树并判断其...

    数据结构 树、二叉树的数据结构 哈夫曼树

    1. 定义并实现二叉树的数据结构(注:其中创建二叉树要求使用广义表或前序遍历方法创建、还要求一个是前序+中序的方法创建)。测试二叉树使用如下的树: A B C D E F 2. 实现哈夫曼树数据结构,使用...

    数据结构-树与二叉树算法汇总

    "树与二叉树算法汇总" 本资源摘要信息主要讨论树与二叉树算法,涵盖树与二叉树的表示、遍历和操作等方面的知识点...树与二叉树算法是数据结构中非常重要的一部分,涵盖了树与二叉树的表示、遍历和操作等方面的知识点。

    数据结构 树 二叉树

    ### 数据结构:树与二叉树 #### 一、知识点概览 1. **二叉树的基本概念**:包括二叉树的定义、特点及分类(如完全二叉树、满二叉树等)。 2. **二叉树的性质**:涉及到节点数量与结构之间的关系,比如叶子节点的...

    数据结构实验-二叉树的基本操作

    一、问题描述 运用二叉链表实现二叉树的基本操作,包括:创建二叉树的存储结构、复制...1、构造二叉树的二叉链表数据结构。 2、实现二叉树的创建、复制、计算二叉树的深度、先根序序列、中根序序列、后根序序列等操作。

    数据结构树和二叉树遍历二叉树和线索二叉树PPT学习教案.pptx

    "数据结构树和二叉树遍历二叉树和线索二叉树PPT学习教案.pptx" 本资源主要讲述了数据结构树和二叉树遍历的相关知识点,包括二叉树的基本概念、二叉树遍历的六种方案、先序、中序、后序遍历算法的实现、线索二叉树的...

    数据结构实验(二叉树)

    二叉树作为一种重要的数据结构,是数据结构实验中常见的研究对象。在这里,我们将深入探讨二叉树的概念、类型、操作以及其实现方式。 **二叉树定义** 二叉树是一种非线性的数据结构,每个节点最多有两个子节点,...

    最优二叉树算法

    最优二叉树 最优二叉树算法

    数据结构C语言版二叉树及其查找结构

    本资源提供了详细的数据结构C语言版二叉树及其查找结构的知识点,包括树的定义、树的特点、二叉树的基本形态、 二叉树的性质、二叉树的存储结构和普通树转换成二叉树等方面的内容,对学习数据结构的新手有很大的帮助...

    数据结构树与二叉树的ppt

    数据结构中的树与二叉树是计算机科学中基础且重要的概念,它们被广泛应用于软件开发、数据库设计、算法分析等领域。清华大学出版社的数据结构教材详细介绍了这些概念,旨在帮助读者理解和掌握这一领域的核心知识。 ...

Global site tag (gtag.js) - Google Analytics