DS博客作业03--树

0.PTA得分截图(215)

1.本周学习总结

1.1 总结树及串内容

串的BF算法

匹配方法:遍历整个串直到找到子串
缺点:效率低,主串需要回溯到上一个遍历点的下一个字符,子串每次都从头开始
优点:是比较容易理解的一种算法
匹配图解:

串的KMP算法

匹配方法:
改进:主串无需回溯,子串不一定需要从头开始遍历

二叉树存储结构、建法、遍历及应用

一般存储结构

typedef struct BiTNode
{
    char data;
    struct BiTNode* lchild, * rchild;
}BTNode, * BTree;

先序建树

BTree CreateTree(char str[], int &i)
{
    BTree T;
    int len;
    len = Strlen(str);
    T = new BTNode;
    if (i > len)
    {
		return NULL;
	}
	if (str[i] == '#')
	{
		return NULL;
	}
	T->data = str[i];
	T->lchild = CreateTree(str, ++i);
	T->rchild = CreateTree(str, ++i);
	return T;
}

层次建树

BTree CreateTree(char str[], int& i)
{
	BTree T;
	int len;
	len = Strlen(str);
	T = new BTNode;
	if (i > len)
	{
		return NULL;
	}
	if (str[i] == '#')
	{
		return NULL;
	}
	T->data = str[i];
	T->lchild = CreateTree(str, ++i);
	T->rchild = CreateTree(str, ++i);
	return T;
}

先序中序后序遍历

void Print(BinTree BT)
{
	if (BT != NULL)
	{
		printf(" %c", BT->Data);//放在这是先序
		PreorderPrintLeaves(BT->Left);
                printf(" %c", BT->Data);//放这是中序
		PreorderPrintLeaves(BT->Right);
                printf(" %c", BT->Data);//放这是后序
	}
}
//区别在于先访问子树还是先录入数据

  • 先序:ABDCEFGH
  • 中序:DBAECGFH
  • 后序:DBEGHFCA

层次遍历

void LevelOrderPrintNodes(BTree LT)
{
	if (LT == NULL)
	{
		cout << "NULL";
		return;
	}
	queue<BTree>BT;
	BTree T;
	int flag = 1;
	BT.push(LT);
	while (!BT.empty())
	{
		T = BT.front();
		BT.pop();
		if (flag == 1 && T != NULL)
		{
			cout << T->data;
			flag = 0;
		}
		else if (flag == 0 && T != NULL)
		{
			cout << " " << T->data;
		}
		if (T->lchild != NULL)
		{
			BT.push(T->lchild);
		}
		if (T->rchild != NULL)
		{
			BT.push(T->rchild);
		}
	}
}

应用:如求二叉树高度(递归法)

int GetHeight(BinTree BT)
{
	if (BT == NULL)return 0;
	if (BT->Left == NULL && BT->Right == NULL)return 1;
	if (GetHeight(BT->Left) > GetHeight(BT->Right))
	{
		return GetHeight(BT->Left) + 1;
	}
	else
	{
		return GetHeight(BT->Right) + 1;
	}
}

树的结构、操作、遍历及应用

双亲结构

typedef struct 
{  
    int data;
   int parent;
} PTree[MaxSize];

孩子结构

typedef struct node
{      
    int data;
    struct node *sons[MaxSons];
    //兄弟链就是在这加上一条指向同层的指针
}  TNode;
  • 遍历操作与二叉树类似

线索二叉树

typedef struct BiTNode 
{
	int data;
	int ltag;
	int rtag;
	struct BiTNode* lchild, *rchild;
}BTNode,*BTree;

线索二叉树利用二叉树空域存放指针指向其它结点

  • 除第一个结点外每个结点有且仅有一个直接前驱结点;除最后一个结点外每一个结点有且仅有一个直接后继结点
  • 根据线索不同分中序和后序线索二叉树

哈夫曼树、并查集

typedef struct 
{
    int weight;//权重
    int parent, left, right;
}HTNode, *HuffmanTree;
  • wpl=叶节点*链路长度
    如:
  • wpl=(7+8+9)*3=72
  • 哈夫曼树是一种带权路径长度最短的二叉树,极大提高了代码的效率,是最优二叉树

哈夫曼编码

  • 从根节点开始,将左孩子编码1,右孩子编码0,直到各节点为止的编码连起来就是哈夫曼编码
  • 如上图所示
    9的编码为000,7的编码为110等

1.2.谈谈你对树的认识及学习体会。

树的知识掌握的不好,用起来不熟练,有些地方解析得不够透彻,就听不懂。

2.阅读代码

2.1 左叶子之和

  • 题目
  • 解题代码

2.1.1 该题的设计思路

  • 该题不直接访问叶子结点,而是在叶子结点的上一个结点来访问左结点,巧妙避开了访问右结点的情况
  • 空间复杂度和时间复杂度都为O(n)

2.1.2 该题的伪代码

//递归法
int sumOfLeftLeaves(struct TreeNode* root)
    sum=0
    if树为空,返回0
    if左子树不空
        if树的左子树为叶节点
            sum=叶节点的值
        else
            sum=sumOfLeftLeaves(左子树)//得到左子树的左叶子的值
    sum+=sumOfLeftLeaves(右子树)//得到右子树左叶子的值并加上左子树的左叶子的值
    返回sum的值 

2.1.3 运行结果

2.1.4分析该题目解题优势及难点

  • 该解法利用了递归,缩短了代码长度,仅使用简单的语法,阅读难度较低
  • 题目难点在于如何避开右叶子仅仅得到左叶子的值

2.2 打劫家舍III


2.2.1设计思路

  • 思路:每次递归时算出该结点使用与不使用的值并返回最大值,关键在于动态比较
  • 时间和空间复杂度都为O(n)

2.2.2伪代码

int getMaxSum(struct TreeNode *root, int *sumRoot, int *sumNoRoot)
    if树为空,返回0
    计算不取当前结点的最大值(存入sumNoRoot)
    计算取当前结点的最大值(sumRoot)
    二者比较返回较大者
int rob(struct TreeNode* root)
    定义sumRoot,sumNoRoot
    调用getMaxSum函数

2.2.3运行结果

2.2.4分析该题目解题优势及难点

  • 题目需要利用动态规划,在递归时要根据结果判断是否是最大值
  • 题目难点在于如何保证所求的值不是俩个直接相连的结点

2.3路径总和III

2.3.1设计思路

  • 思路:双递归法,类先序遍历,找到符合要求的值并返回个数
  • 时间和空间复杂度都为O(n)

2.3.2伪代码

int helper(TreeNode* root, int sum)//sum的值为要求的值
    if树为空,返回0
    sum-当前结点值
    返回(如果sum为0证明减去的结点值刚好=sum,返回1,否则0)+helper(左子树,sum)+helper(右子树,sum)
int pathSum(TreeNode* root, int sum)
    if树为空,返回0
    返回调用函数helper后的结果

2.3.3运行结果

2.3.4分析该题目解题优势及难点

  • 本题极大利用递归解决,大幅缩短代码
  • 难点:找到链路中和为某个值的链路

2.4另一个树的子树

2.4.1设计思路

  • 思路:对每一棵子树进行比较
  • 时间和空间复杂度O(n)

2.4.2伪代码

bool compare (struct TreeNode* p1,struct TreeNode* p2)
    if p1,p2都为空,返回true
    if p1,p2若一方为空一方不空,返回false//因为上一句已经比较过都为空的情况,不会出现都为空返回false
    if p1的数据不等于p2数据,返回false
    返回p1p2左右子树比较地结果,同时匹配才返回正确
bool isSubtree(struct TreeNode* s, struct TreeNode* t)
    if s为空,返回false
    对所有子树调用compare函数比较,只要有任意一颗子树和目标子树匹配就返回正确

2.4.3运行结果

2.4.4分析该题目解题优势及难点

  • 解法利用递归节省大量代码,而不是一个结点一个结点地去比较,是一种较好的方法
  • 难点:以什么样的方法比较子树与目标树
posted @ 2020-04-12 22:38  林盛泓  阅读(244)  评论(0编辑  收藏  举报