13 二叉树:建立存储结构(前序输入次序) &&二叉树专题

目录

首先讲讲指针的引用 *&

然后我们再复习一下typedef的用法。

然后我们来创建二叉树

二叉树的建立

首先二叉树的存储结构(实际用代码体现)分为顺序存储和链式存储两种,但一般情况我们都用链式存储结构。

部分内容转自指针的引用 *&_MAGDB的博客-CSDN博客_指针的引用

首先讲讲指针的引用 *&

以下代码
 

void shit(student *p)
{
p->data=0;
p=p->next;
}

void shit2(student &*p)
{
p->data=0;
p=p->next;
}

请问shit函数和shit2函数有什么区别呢? 

对于p->data这一步两个函数都可以修改实参的data值。

但是重点来了

对于p=p->next;这一步,shit不可以让实参中的p指向下一位,而shit2可以改变实参的下一位。

以下为转载。

注意:
能否理解的重点是
如果不是指针引用
指针的指向改变并不能影响原指针的指向
指针指向的值的改变可以影响到原值

也就是说
如果不是指针引用,
形参指针指向改变对实参指针指向没有影响,
形参指针指向值大小改变,实参指针指向值大小随之改变

然后我们再复习一下typedef的用法

//以下代码run under c language

typedef struct tagPOINT
{
    int x;
    int y;
}POINT;
//那么POINT a相当于struct tagPOINT a;

typedef struct tagPOINT
{
    int x;
    int y;
}POINT,* k;
//那么struct tagPOINT * a相当于k a;

然后我们来创建二叉树

struct student
{
	char data;
	student* left;
	student* right;
};

我习惯用student来包装所有目标物,大家习惯就好。

书上一般都是先告诉你遍历的种类,然后再教你如何建立二叉树。

因为下面的建立需要用的遍历的知识。但其实你不知道遍历也可以。我觉得应该先写如何建立二叉树,然后再来介绍遍历的种类。

下面是用的先序遍历来建立二叉链表

//此方法是先序遍历顺序建立二叉链表
void creat(student *&T)
{
	char ch;
	cin >> ch;
	if (ch == '#')
	{
		T = NULL;
	}//但凡输入了#号 就代表这是个空树
	else
	{
		T = new student;
		T->data=ch;
		creat(T->left);
		creat(T->right);
	}
}

现在举一个例子。

例如我们要实现一个二叉树如图所示

 那我们用下面这段代码的时候

 应该怎么输入呢?

struct student
{
	char data;
	student* left;
	student* right;
};
//此方法是先序遍历顺序建立二叉链表
void creat(student *&T)
{
	char ch;
	cin >> ch;
	if (ch == '#')
	{
		T = NULL;
	}//但凡输入了#号 就代表这是个空树
	else
	{
		T = new student;
		T->data=ch;
		creat(T->left);
		creat(T->right);
	}
}

输入:

ABC##DE#G##F###

-----------------

为什么要这样输入呢?为什么输入顺序是这样的呢?建议你去看B站视频看完应该就能够理解了。

【纯干货】三分钟教会你遍历二叉树!学不会举报我!!_哔哩哔哩_bilibili

下面例题一道

13 二叉树:建立存储结构(前序输入次序)

作者: 冯向阳时间限制: 1S章节: DS:树

截止日期: 2022-06-30 23:55:00

问题描述 :

目的:使用C++模板设计并逐步完善二叉树的抽象数据类型(ADT)。

内容:(1)请参照链表的ADT模板,设计二叉树并逐步完善的抽象数据类型。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。参考教材、课件,以及网盘中的链表ADT原型文件,自行设计二叉树的ADT。)

注意:二叉树ADT的基本操作的算法设计很多要用到递归的程序设计方法。

(2)基本操作1:二叉树的二叉链表存储形式的建立,完成后将其加入到二叉树的ADT基本操作集中。

要求设计一个递归算法,将二叉树转化为二叉链表的存储形式。

初始条件:definition给出二叉树T的定义(先序序列。无孩子或指针为空的情形,算法通过特殊分隔符识别(输入)),至少有1个根结点。

输出:按definition构造二叉树的二叉链表。

注意:由于测试数据的显示需建立在二叉树的遍历基础上。因此,请在设计好二叉树的三种遍历算法之后(基本操作2),再进行测试。

参考函数代码:

//建立二叉树的存储结构 (外壳) 

template<class ElemType>

void CreateTree(BinaryTree<ElemType> &T, ElemType &str, ElemType &empty){

    ElemType tmp;

    vector<ElemType> t;

    

    stringstream input_T(str);

    while(input_T >> tmp){

         t.push_back(tmp);

    }

    BinaryTreeNode<ElemType> *root;

    int num = 0;

    root = T.CreateBinaryTree(t, empty, num);

    T.SetRoot(root);    

}

//建立二叉树的存储结构 (递归部分,成员函数)

template<class ElemType>

BinaryTreeNode<ElemType>* BinaryTree<ElemType>::CreateBinaryTree(vector<ElemType> &x, ElemType &empty, int &n){

        ElemType ch = x[n];

        n++;

        if (ch == empty)

        {

            return NULL;

        }

        else

        {   

            BinaryTreeNode<ElemType> *Node = new BinaryTreeNode<ElemType>;

            Node->data = ch;

            Node->LChild = CreateBinaryTree(x, empty, n);

            Node->RChild = CreateBinaryTree(x, empty, n);

            return Node;

        }

}

二叉树ADT原型参考如下:

/* 二叉表的结点定义 */
template<class ElemType>
struct BinaryTreeNode
{
       ElemType data;
       BinaryTreeNode<ElemType> *LChild, *RChild;
       BinaryTreeNode() : LChild(NULL), RChild(NULL){} //构造函数1,用于构造根结点
       BinaryTreeNode(const ElemType &item, BinaryTreeNode<ElemType> *Lptr = NULL, BinaryTreeNode<ElemType> *Rptr = NULL) //构造函数2,用于构造其他结点  
       //函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面
       {
           LChild = Lptr;
           RChild = Rptr;
           data = item;
       }
      
       ElemType getData(){ return data;}  //取得结点中的数据
       void SetLChild( BinaryTreeNode<ElemType> *link ){ LChild = link; }  //修改结点的左孩子域
       void SetRChild( BinaryTreeNode<ElemType> *link ){ RChild = link; }  //修改结点的右孩子域
       void SetData( ElemType value ){ data = value; }   //修改结点的data域            
       BinaryTreeNode<ElemType> * GetLChild() const{ return LChild;} //获取左孩子结点
       BinaryTreeNode<ElemType> * GetRChild() const{ return RChild;} //获取左孩子结点

};

//二叉树 

template<class ElemType>

class BinaryTree{

   private:

      BinaryTreeNode<ElemType> *root;   // 头指针

      void BinaryTreeDestroy_Cursive( BinaryTreeNode<ElemType> *T ); //销毁树(递归准备,private)

            

   public:

      //无参数的构造函数

      BinaryTree():root(NULL){}

      //带参数的构造函数

      BinaryTree(const ElemType &item){root = new BinaryTreeNode<ElemType>(item);}

      //生成树

      void makeBinaryTree( const ElemType &item, BinaryTree &left, BinaryTree &right); 

      //拷贝构造函数

      //LinkQueue(LinkQueueList<ElemType> &Queue);

      //析构函数

      ~BinaryTree(){BinaryTreeDestroy();}

      //重载函数:赋值

      //LinkList<ElemType>& operator=(LinkList<ElemType> &List);

      //销毁树 

      void BinaryTreeDestroy();

      //销毁子树 

      void ChildDestroy(int flag);

      //返回二叉树结点的个数

      int BinaryTreeSize( BinaryTreeNode<ElemType> *T ) const;

      //判断二叉树是否为空

      bool BinaryTreeisEmpty() const{return root == NULL;}

      //获取根结点元素值 

      ElemType GetRootData() const{ return root->data;}

      //bool Location(ElemType &x, BinaryTreeNode<ElemType> * &location);

      //设置根结点 

      void SetRoot(BinaryTreeNode<ElemType> * p){ root = p;}

      //获取根结点 

      BinaryTreeNode<ElemType> * GetRoot() const{ return root;}

      //前序遍历 

      bool PreOrderTraverse( BinaryTreeNode<ElemType> *T, bool (*visit)(BinaryTreeNode<ElemType> *T, int &num), int &num ) const;  //前序遍历(递归)//num的初始值为0,作用为控制输出格式(最后1个结点后不加“,”)

      //中序遍历 

      bool InOrderTraverse( BinaryTreeNode<ElemType> *T, bool (*visit)(BinaryTreeNode<ElemType> *T, int &num), int &num ) const;  //中序遍历(递归)

      //后序遍历 

      bool PostOrderTraverse( BinaryTreeNode<ElemType> *T, bool (*visit)(BinaryTreeNode<ElemType> *T, int &num), int &num ) const;  //后序遍历(递归)

      //建立二叉树的存储结构

      BinaryTreeNode<ElemType>* CreateBinaryTree(vector<ElemType> &x, ElemType &empty, int &n);

};

输入说明 :

第一行:表示无孩子或指针为空的特殊分隔符

第二行:二叉树的先序序列(结点元素之间以空格分隔)

输出说明 :

第一行:二叉树先序遍历结果

第二行:二叉树中序遍历结果

第三行:二叉树后序遍历结果

输入范例 :

null
A B null C D null null E null null F null G null H null null

输出范例 :

A,B,C,D,E,F,G,H
B,D,C,E,A,F,G,H
D,E,C,B,H,G,F,A

#include<iostream>
using namespace std;
bool m = 0;
bool m1 = 0;
bool m2 = 0;
struct student
{
	string data;
	student* left;
	student* right;
};
//此方法是先序遍历顺序建立二叉链表---即二叉树的存储结构(二叉树的实际样子)
void creat(student *&T,string kk)
{
	string ch;
	cin >> ch;
	if (ch == kk)
	{
		T = NULL;
	}//但凡输入了#号 该节点下一位停止
	else
	{
		T = new student;
		T->data=ch;
		creat(T->left,kk);
		creat(T->right,kk);
	}
}
//用递归来遍历
void prescan(student *T)//先序遍历
{
	
	if (T == NULL)
	{
	
		return;
	}
	else
	{
		if (m == 1)
		{
			cout << ',';
		}
		cout << T->data;
		m = 1;
		prescan(T->left);
		prescan(T->right);
	}

}

void midscan(student* T)//中序遍历
{
	if (T == NULL)
	{
		return;
	}
	else
	{

		midscan(T->left);
		if (m1 == 1)
		{
			cout << ',';
		}
		cout << T->data;
		m1 = 1;
		midscan(T->right);
	}
	
}

void lastscan(student* T)//后序遍历二叉树
{
	if (T == NULL)
	{

		return;
	}
	else
	{
		lastscan(T->left);
		lastscan(T->right);
		if (m2 == 1)
		{
			cout << ',';
		}
		cout << T->data;
		m2 = 1;
	

	
	}
	
}

void specialscan()//非递归遍历 我现在还不会 会了补上
{
}
int caculate(student *T)
{
	if (T == NULL)
	{
		return 0;
	}
	else
	{
		return 1 + caculate(T->left) + caculate(T->right);
	}
}

int main()
{
	student *head;
	string kk;
	cin >> kk;

	creat(head,kk);
	prescan(head);
	cout << endl;
	midscan(head);
	cout << endl;
	lastscan(head);
	cout << endl;
	return 0;
}

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. 算法的基本概念 利用计算机算法为计算机解题的过程实际上是在实施某种算法。 (1)算法的基本特征 算法一般具有4个基本特征:可行性、确定性、有穷性、拥有足够的情报。 (2)算法的基本运算和操作 算法的基本运算和操作包括:算术运算、逻辑运算、关系运算、数据传输。 (3)算法的3种基本控制结构 算法的3种基本控制结构是:顺序结构、选择结构、循环结构。 (4)算法基本设计方法 算法基本设计方法:列举法、归纳法、递推、递归、减半递推技术、回溯法。 (5)指令系统 所谓指令系统指的是一个计算机系统能执行的所有指令的集合。 (2)数据结构研究的3个方面 ① 数据集合中各数据元素之间所固有的逻辑关系,即数据的逻辑结构; ② 在对数据进行处理时,各数据元素在计算机中的存储关系,即数据的存储结构; ③ 对各种数据结构进行的运算。 2. 逻辑结构 数据的逻辑结构是对数据元素之间的逻辑关系的描述,它可以用一个数据元素的集合和定义在此集合中的若干关系来表示。数据的逻辑结构有两个要素:一是数据元素的集合,通常记为D;二是D上的关系,它反映了数据元素之间的前后件关系,通常记为R。一个数据结构可以表示成:B=(D,R) 其中,B表示数据结构。为了反映D中各数据元素之间的前后件关系,一般用二元组来表示。 例如,如果把一年四季看作一个数据结构,则可表示成:B =(D,R) D ={春季,夏季,秋季,冬季} R ={(春季,夏季),(夏季,秋季),(秋季,冬季)} 3. 存储结构 数据的逻辑结构在计算机存储空间中的存放形式称为数据的存储结构(也称数据的物理结构)。 由于数据元素在计算机存储空间中的位置关系可能与逻辑关系不同,因此,为了表示存放在计算机存储空间中的各数据元素之间的逻辑关系(即前后件关系),在数据的存储结构中,不仅要存放各数据元素的信息,还需要存放各数据元素之间的前后件关系的信息。 一种数据的逻辑结构根据需要可以表示成多种存储结构,常用的存储结构有顺序、链接等存储结构。 顺序存储方式主要用于线性的数据结构,它把逻辑上相邻的数据元素存储在物理上相邻的存储单元里,结点之间的关系由存储单元的邻接关系来体现。 链式存储结构就是在每个结点中至少包含一个指针域,用指针来体现数据元素之间逻辑上的联系。 1.2.2 线性结构和非线性结构 根据数据结构中各数据元素之间前后件关系的复杂程度,一般将数据结构分为两大类型:线性结构与非线性结构。 (1)如果一个非空的数据结构满足下列两个条件: ① 有且只有一个根结点; ② 每一个结点最多有一个前件,也最多有一个后件。 则称该数据结构为线性结构。线性结构又称线性表。在一个线性结构中插入或删除任何一个结点后还应是线性结构。栈、队列、串等都为线性结构。 如果一个数据结构不是线性结构,则称之为非线性结构。数组、广义表、树和图等数据结构都是非线性结构。 (2)线性表的顺序存储结构具有以下两个基本特点: ① 线性表中所有元素所占的存储空间是连续的; ② 线性表中各数据元素在存储空间中是按逻辑顺序依次存放的。 元素ai的存储地址为:ADR(ai)=ADR(a1)+(i-1)k,ADR(a1)为第一个元素的地址,k代表每个元素占的字节数。 (3)顺序表的运算有查找、插入、删除3种。 1.3 栈 1. 栈的基本概念 栈(stack)是一种特殊的线性表,是限定只在一端进行插入与删除的线性表。 在栈中,一端是封闭的,既不允许进行插入元素,也不允许删除元素;另一端是开口的,允许插入和删除元素。通常称插入、删除的这一端为栈顶,另一端为栈底。当表中没有元素时称为空栈。栈顶元素总是最后被插入的元素,从而也是最先被删除的元素;栈底元素总是最先被插入的元素,从而也是最后才能被删除的元素。 栈是按照“先进后出”或“后进先出”的原则组织数据的。例如,枪械的子弹匣就可以用来形象的表示栈结构。子弹匣的一端是完全封闭的,最后被压入弹匣的子弹总是最先被弹出,而最先被压入的子弹最后才能被弹出。 二级公共基础知识速学教程 2. 栈的顺序存储及其运算 栈的基本运算有3种:入栈、退栈与读栈顶元素。 ① 入栈运算:在栈顶位置插入一个新元素; ② 退栈运算:取出栈顶元素并赋给一个指定的变量; ③ 读栈顶元素:将栈顶元素赋给一个指定的变量。 1.4 队列 1. 队列的基本概念 队列是只允许在一端进行删除,在另一端进行插入的顺序表,通常将允许删除的这一端称为队头,允许插入的这一端称为队尾。当表中没有元素时称为空队列。 队列的修改是依照先进先出的原则进行的,因此队列也称为先进先出的线性表,或者后进后出的线性表。例如:火车进遂道,最先进遂道的是火车头,最后是火车尾,而火车出遂道的时候也是火车头先出,最后出的是火车尾。若有队列: Q =(q1,q2,…,qn) 那么,q1为队头元素(排头
今年9月份参加计算机二级考试的同学请转载 作者:天使~之戀 已被分享1次 评论(0) 复制链接 分享 转载 删除 下面的138道题目,在二级考试中命中率极高。 一、选择题 (1) 下面叙述正确的是(C) A. 算法的执行效率与数据的存储结构无关 B. 算法的空间复杂度是指算法程序中指令(或语句)的条数 C. 算法的有穷性是指算法必须能在执行有限个步骤之后终止 D. 以上三种描述都不对 (2) 以下数据结构中不属于线性数据结构的是(C) A. 队列 B. 线性表 C. 二叉树 D. 栈 (3) 在一棵二叉树上第5层的结点数最多是(B) 注:由公式2k-1得 A. 8 B. 16 C. 32 D. 15 (4) 下面描述中,符合结构化程序设计风格的是(A) A. 使用顺序、选择和重复(循环)三种基本控制结构表示程序的控制逻辑 B. 模块只有一个入口,可以有多个出口 C. 注重提高程序的执行效率 D. 不使用goto语句 (5) 下面概念中,不属于面向对象方法的是 (D) 注:P55-58 A. 对象 B. 继承 C. 类 D. 过程调用 (6) 在结构化方法中,用数据流程图(DFD)作为描述工具的软件开发阶段是(B) A. 可行性分析 B. 需求分析 C. 详细设计 D. 程序编码 (7) 在软件开发中,下面任务不属于设计阶段的是(D) A. 数据结构设计 B. 给出系统模块结构 C. 定义模块算法 D. 定义需求并建立系统模型 (8) 数据库系统的核心是(B) A. 数据模型 B. 数据库管理系统 C. 软件工具 D. 数据库 (9) 下列叙述中正确的是(C) A.数据库是一个独立的系统,不需要操作系统的支持 B.数据库设计是指设计数据库管理系统C.数据库技术的根本目标是要解决数据共享的问题 D.数据库系统中,数据的物理结构必须与逻辑结构一致 (10) 下列模式中,能够给出数据库物理存储结构与物理存取方法的是(A) 注:P108 A. 内模式 B. 外模式 C. 概念模式 D. 逻辑模式 (11) 算法的时间复杂度是指(C) A. 执行算法程序所需要的时间 B. 算法程序的长度 C. 算法执行过程中所需要的基本运算次数 D. 算法程序中的指令条数 (12) 算法的空间复杂度是指(D) A. 算法程序的长度 B. 算法程序中的指令条数 C. 算法程序所占的存储空间 D. 算法执行过程中所需要的存储空间 (13) 设一棵完全二叉树共有699个结点,则在该二叉树中的叶子结点数为(B) 注:利用公式n=n0+n1+n2、n0=n2+1和完全二叉数的特点可求出 A. 349 B. 350 C. 255 D. 351 (14) 结构化程序设计主要强调的是(B) A.程序的规模 B.程序的易读性 C.程序的执行效率 D.程序的可移植性 (15) 在软件生命周期中,能准确地确定软件系统必须做什么和必须具备哪些功能的阶段是(D) 注:即第一个阶段 A. 概要设计 B. 详细设计 C. 可行性分析 D. 需求分析 (16) 数据流图用于抽象描述一个软件的逻辑模型,数据流图由一些特定的图符构成。下列图符名标识的图符不属于数据流图合法图符的是(A) 注:P67 A. 控制流 B. 加工 C. 数据存储 D. 源和潭 (17) 软件需求分析阶段的工作,可以分为四个方面:需求获取、需求分析、编写需求规格说明书以及(B) 注:P66 A. 阶段性报告 B. 需求评审 C. 总结 D. 都不正确 (18) 下述关于数据库系统的叙述中正确的是(A) A. 数据库系统减少了数据冗余 B. 数据库系统避免了一切冗余 C. 数据库系统中数据的一致性是指数据类型的一致 D. 数据库系统比文件系统能管理更多的数据 (19) 关系表中的每一横行称为一个(A) A. 元组 B. 字段 C. 属性 D. 码 (20) 数据库设计包括两个方面的设计内容,它们是(A) A. 概念设计和逻辑设计 B. 模式设计和内模式设计 C. 内模式设计和物理设计 D. 结构特性设计和行为特性设计 (21) 下列叙述中正确的是(A) A. 线性表是线性结构 B. 栈与队列是非线性结构 C. 线性链表是非线性结构 D. 二叉树是线性结构 (22) 下列关于栈的叙述中正确的是(D) A. 在栈中只能插入数据 B. 在栈中只能删除数据 C. 栈是先进先出的线性表 D. 栈是先进后出的线性表 (23) 下列关于队列的叙述中正确的是(C) A. 在队列中只能插入数据 B. 在队列中只能删除数据 C. 队列是先进先出的线性表 D. 队列是先进后出的线性表 (24) 对建立良好的程序设计风格,下面描述正确的是(A) 注:P48 A. 程序应简单、清晰、可读性好 B. 符号名的命名要符合语法 C. 充
5.1 数的逻辑结构 5.1.1 1、树的定义 在树中常常将数据元素称为结点 (1)有且仅有一个特定的称为根的结点; (2)当n>1时,除根结点之外的其余结点被分成m(m>0)个互不相交的有限集合T1,T2,•••Tm,其中每个集合又是一棵树,并称为这个节点的子树。 2、树的基本术语: 结点的度、树的度 叶子节点、分支结点 孩子节点、分支结点、兄弟节点 路径、路径长度 祖先、子孙 结点的层数、树的深度(高度) 层序编号 有序树、无序树 森林 5.1.2 树的抽象数据类型定义 5.1.3树的遍历操作 1、前序遍历 树的前序遍历操作定义为: 若树为空,则空操作返回;否则 (1)访问根结点 (2)按照从左向右的顺序前序遍历根结点的每一棵子树。 2、中序遍历 树的中序遍历操作定义为: 若树为空,则空操作返回;否则 (1)按照从左向右的顺序后序遍历根结点的每一棵子树; (2)访问根结点。 3、层序遍历 树的层序遍历也称作树的广泛遍历,其操作定义为树的第一层开始,自上而下逐层遍历,在同一层中,按从左向右的顺序对结点逐个访问。 5.2树的存储结构 5.2.1 双亲表示法 由树的定义可知,树中每个结点都有且仅有一个双亲结点。所以利用这一特性,可以用一维数组来存储各个结点,数组中一个元素对应一个结点,数组元素包括树中结点的数据信息以及该结点的双亲在数组中的下标。 其中: Data为数据域,存储树中结点的数据信息; Parent为指针即游标,存储该结点的双亲在数组中的小标。 5.2.2孩子表示法 1、多重链表表示法 (1)指针域的个数等于该结点的度。 (2)指针域的个数等于树的度。 2、孩子链表表示法 把孩子看成一个线性表,且以单链表存储,称为该结点的孩子链表。则n个结点有n个孩子链表。 孩子节点有两类:孩子节点、表头结点。 5.2.3 双亲孩子表示法 即将双亲表示法和孩子链表表示法相结合的存储方法。仍将各结点的孩子分别组成单链表,同时用一维数组顺序存储树中的各结点,数组元素除了包括结点的数据信息和该结点的孩子链表的头指针之外,还增设一个域存储该结点的双亲在数组的下标。 5.2.4孩子兄弟表示法 又称二链表表示法,其方法是链表中每个结点除数据域外,还设置了两个指针分别指向该结点的第一个孩子和右兄弟链表的结构: Firstchild data rightsib 指针域,存储第一个孩子结点的存储地址 数据域,存储该结点的数据信息 指针域,存储该结点右兄弟结点的存储地址 5.3二叉树的逻辑结构 最简单的树结构,特别适合计算机处理,而且任何数都可以简单的转换为二叉树。(重点内容) 5.3.1二叉树的定义 二叉树是n(n>=0)个结点的有限集合,该集合或者为空集,或者有一个根节点和两棵互不相交的、分别称为根节点的左子树和右子树的二叉树组成。 二叉树具有五种基本形态: 1、空二叉树; 2、只有一个根结点; 3、根结点只有左子树; 4、根结点只有右子树; 5、根结点既有左子树又有右子树 特殊二叉树: 1、斜树; 2、满二叉树; 3、完全二叉树; 5.3.2二叉树的基本性质 性质5-1 二叉树的第i层上最多有2^(i-1)个结点(i>=1)。 性质5-2 在一棵深度为k的二叉树中,最多有2^k-1个结点,最少有k个结点。 性质5-3 在一棵二叉树中,如果叶子结点的个数为n0,度为2的结点个数为n2,则n0=n2+1. 性质5-4 具有n个结点的完全二叉树的深度为【log2^n】+1。 性质5-5 对一棵具有n个结点的完全二叉树中的结点从一开始按层序编号,则对于任意的编号为i(1<=i<=n)的结点,有: (1)如果i>1,则结点i的双亲的编号为【i/2】;否则结点i是根结点,无双亲。 (2)如果2i<=n,则 结点i的左孩子的编号为2i;否则结点i无左孩子。 (3)如果2i+1<=n,则结点i的右孩子的编号为2i+1,否则结点i无右孩子。 5.3.3 二叉树的抽象数据类型定义 同树类似,在不同的应用中,二叉树的基本操作不尽相同。 5.3.4 二叉树的遍历操作 二叉树的遍历是指从根节点出发,按照某种次序访问二叉树是所有结点,使得每个结点被访问一次且仅被访问一次。由于二叉树中每个结点都可能有两个子树,因此需要寻找一条合适的搜索路径。 1、前序遍历 前序遍历二叉树操作定义为: 若树为空,则空操作返回;否则 (1)访问根结点 (2)前序遍历根结点的左子树 (3)前序遍历根结点的右子树 2、中序遍历 中序遍历二叉树操作定义为: 若树为空,则空操作返回;否则 (1)中序遍历根结点的左子树 (2)访问根结点 (3)中序遍历根结点的右子树 3、后序遍历 后序遍历根结点的左子树 后序遍历根结点的右子树 访问根结点 4、层序遍历 二叉树的层序遍历是指从二叉树的第一层开始,从上之下逐层遍历,在同一层中,按从左到右的顺序对结点逐个访问。 5.4 二叉树存储结构及实现 5.4.1 顺序存储结构 具体步骤: (1)将二叉树按完全二叉树编号。 (2)将二叉树中的结点一编号顺序存储到一维数组中。 5.4.2 二叉链表 基本思想: 令二叉树的每个结点对应一个链表结点,链表结点除了存放于二叉树结点有关的数据信息外,还要设置指示左右孩子的指针。 5.4.3 三叉链表 在二叉链表存储方式下,从某个结点出发可以直接访问它的孩子结点,但要找到它的双亲结点,则需要从根节点开始搜索,最坏的情况下,需要遍历整个二叉链表。此时采用三叉树链表储存二叉树。 其中,data,lchild,rchild三个域的含义同二叉树,parent域为指向该结点的双亲结点指针。 5.4.4 线索链表 按照某种遍历次序二叉树进行遍历,可以把二叉树中所有结点排成一个线性序列。在集体应用中,有时需要访问二叉树中的结点在某种遍历序列中前驱和后继,此时,在存储结构中应该保存结点在某种遍历序列中的前驱和后继信息。 前驱和后继结点的指针称为线索,加上线索的二叉树称为线索二叉树,加上线索的二叉链表称为线索链表。 5.5 二叉树遍历的非递归算法 5.5.1 前序遍历非递归算法 关键:在前序遍历过某个左子树后,如何找到该结点的右子树的根指针。 一般的前序遍历执行过程中,设要遍历二叉树的根指针为bt,可能出现两种情况: (1)若bt!=NULL,则表明当前二叉树不为空,此时,应输入根结点bt的值并将bt保存到栈中,准备继续遍历bt的左子树。 (2)若bt=NULL,则表明以bt为根指针的二叉树遍历完毕,并且bt是栈顶指针所指结点的左子树,若栈不空,则应根据栈顶指针所指结点找到待遍历右子树的根指针并赋予bt,以继续遍历下去;若栈空,则表明整个二叉树遍历完毕。 5.5.2 中序遍历非递归算法 此算法只是需要将前序遍历的非递归算法中输出的语句cout<<bt->data移到bt=s[top--]之后即可。 5.5.3 后序遍历非递归算法 后序遍历的不同在于:结点要出入两次栈,出两次栈,这种情况的含义和处理方法为: (1)第一次出栈:只遍历晚左子树,右子树尚未遍历,则该结点不出栈,利用栈顶结点找到它的右子树,准备遍历它的右子树。 (2)第二次出栈:遍历完右子树,该结点出栈,并访问它。 设根指针为bt,则可能有以下两种情况: (1)若bt!=NULL,则bt及标志flag入栈,遍历其左子树。 (2)若bt=NULL,此时栈空,则整个遍历结束;若栈不空,则表明栈顶结点的左子树或右子树已遍历结束。若栈顶点的标志flag=1,则表明栈结点的左子树已遍历完毕,将flag修改为2,修改为2,并遍历栈定点的右子树;若栈顶结点的标志flag=2,则表明栈结点的右子树也遍历完毕,输出栈顶结点。 5.6 树、森林与二叉树的转换 1.树转换为二叉树 将一棵树转换为二叉树的方法为: (1)加线——树中所有相邻的兄弟结点之间加一条线; (2)去线——对树中的每个节点,只保留它与第一个孩子结点之间的连线,删去它与其他孩子结点之间的连线。 (3)层次调节——以根结点为轴心,将树顺时针转动一定角度,使之层次分明。 2.森林转换成二叉树 (1)将森林中的每一棵二叉树转化成二叉树; (2)从第二课二叉树开始,依次把后一棵二叉树的根结点作为一棵二叉树根节点的右孩子,当所有二叉树连起来后,此时所得到的二叉树就是由森林转换得到的二叉树。 3、二叉树转换为树或森林 (1)加线——若某个结点x是其双亲y的左孩子,则把结点x的右孩子、右孩子的右孩子、……,都与结点y用线连起来; (2)去线——删去原二叉树中所有的双亲结点与右孩子结点的连线; (3)层次调整——整理由(1)、(2)两步所得到的树或森林,使之层次分明。 (4)森林的遍历 两种遍历方法;前序遍历后续遍历。 5.7 应用举例 5.7.1 二叉树的应用举例——哈夫曼及哈夫曼编码 1、哈夫曼树也称最优二叉树,在实际中有着广泛的应用。 叶子节点的权值 是对叶子结点赋予的一个有意义的数值量。 二叉树的带权路径长度 设二叉树具有n个带权值的叶子节点,从根节点到叶子节点的路径长度与相应的叶子节点权值的乘积之和叫做二叉树的带权路径长度,记为: WPL=EWkLk 哈夫曼树 给定一组具有确定权值的叶子结点,可以构造出不同的二叉树,将其中带权值路径长度最小的二叉树称为哈夫曼树。 哈夫曼算法基本思想: (1)初始化:由给定的n个权值构造n棵只有一个根结点的二叉树,从而得到一个二叉树集合。 (2)选取与合并:在F中选取根结点的权值最小的两棵二叉树分别作为左、右子树构造一棵新的二叉树,这棵新的二叉树的根结点的权值为其左右子树根结点的权值之和。 (3)删除与加入:在F中删除作为左、右子树的两棵二叉树,并将新建的二叉树加入到F中。 (4)重复(2)(3)两步的操作,当集合F只剩下一棵二叉树时这棵二叉树便是哈夫曼树。 2、哈夫曼编码 在进行程序设计时,通常给每一个字符记一个单独的代码来表示一组字符,我们称之为编码。
22春"计算机科学与技术"专业《数据结构》在线作业答案参考 1. 判断线索二叉树中某结点p有右子女的条件是( )。 A.p->rtag==1 B.p->rtag==0 C.p->lchild!=NULL D.p!=NULL 参考答案:B 2. 邻接表法只能用于有向图存储。( ) A.正确 B.错误 参考答案:B 3. 若采用邻接矩阵法存储一个n个顶点的无向图,则该邻接矩阵是一个( )。 A.上三角矩阵 B.稀疏矩阵 C.对角矩阵 D.对称矩阵 参考答案:D 4. 栈和队列都是限制存取点的线性结构。( ) A.正确 B.错误 参考答案:A 5. 若输入序列为1,2,3,4,5,6,则通过一个栈可以输出序列3,2,5,6,4,1。( ) A.正确 B.错误 参考答案:A 22春"计算机科学与技术"专业《数据结构》在线作业含答案参考9全文共4页,当前为第1页。6. 顺序存储方式的优点是存储密度大,且插入、删除运算效率高。( ) A.正确 B.错误 参考答案:B 22春"计算机科学与技术"专业《数据结构》在线作业含答案参考9全文共4页,当前为第1页。 7. 平衡二叉树的平衡因子只可能是-1、0、1。( ) A.正确 B.错误 参考答案:A 8. 对长度为n的关键字序列进行堆排序的空间复杂度为( )。 A.O(log2n) B.O(1) C.O(n) D.O(n*log2n) 参考答案:B 9. 在对链队列作出队操作时,不会改变front指针的值。( ) A、错误 B、正确 参考答案:A 10. 下列序列中,不构成堆的是( )。 A.(1,2,5,3,4,6,7,8,9,10) B.(10,5,8,4,2,6,7,1,3) C.(10,9,8,7,3,5,4,6,2) D.(1,2,3,4,10,9,8,7,6,5) 参考答案:D 22春"计算机科学与技术"专业《数据结构》在线作业含答案参考9全文共4页,当前为第2页。11. 下列关于数据结构基本概念的叙述中,正确的是( )。 A.数据的逻辑结构分为表结构和树结构 B.数据的存储结构分为线性结构和非线性结构 C.数据元素是数据的基本单位 D.结点是有独立含义的数据最小单位 参考答案:C 22春"计算机科学与技术"专业《数据结构》在线作业含答案参考9全文共4页,当前为第2页。 12. 允许对队列进行的操作有( )。 A.对队列中的元素排序 B.取出最近进队的元素 C.在队头元素之前插入元素 D.删除队头元素 参考答案:D 13. 下面关于串的叙述中,哪一个是不正确的?( ) A.空串是由空格构成的串 B.模式匹配是串的一种重要运算 C.串是字符的有限序列 D.串既可以采用顺序存储,也可以采用链式存储 参考答案:A 14. head指向的带表头结点的单链表为空的判定条件是( )。 A.head->next==head B.head->next==NULL C.head==NULL D.head!=NULL 参考答案:B 15. 任何一棵二叉树的叶结点在前序、中序和后序遍历序列中的相对次序( )。 A.稍有改变 B.发生改变 C.不能确定 D.不发生改变 参考答案:D 16. 最小生成树问题是构造带权连通图(网)的最小代价生成树。( ) A.正确 B.错误 参考答案:A 22春"计算机科学与技术"专业《数据结构》在线作业含答案参考9全文共4页,当前为第3页。17. 数据的逻辑结构描述数据元素之间的逻辑关系,与存储方式无关。( ) A、错误 B、正确 参考答案:B 22春"计算机科学与技术"专业《数据结构》在线作业含答案参考9全文共4页,当前为第3页。 18. 将森树转成二叉树,根结点没有右子树。( ) A.正确 B.错误 参考答案:B 19. 设F是一个森林,B是由F转换得到的二叉树,F中有n个非叶结点,则B中右指针域为空的结点有( ) A.n-1 B.n C.n+1 D.n+2 参考答案:B 22春"计算机科学与技术"专业《数据结构》在线作业含答案参考9全文共4页,当前为第4页。20. 空格串的长度是空格的个数。( ) A、错误 B、正确 参考答案:B 22春"计算机科学与技术"专业《数据结构》在线作业含答案参考9全文共4页,当前为第4页。 22春"计算机科学与技术"专业《数据结构》在线作业含答案参考9

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

杨骅麟(Patrick Young)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值