一、学习内容
第五章主要学习了树和二叉树。
树的结构定义时递归的定义,所以在代码实现时会发现大部分都是利用了递归的思路。
二叉树是特殊的一种树,每个结点至多只有两颗子树。二叉树有五个性质,可以用来计算结点个数、深度等。
二叉树的存储:同样有顺序存储和链式存储。
顺序存储仅适用于完全二叉树,不然容易造成极大的空间浪费。
链式存储则更适合于一般的二叉树。
typedef struct BiTNode { TElemType data;//数据域 struct BiTNode *lchild, *rchild;//左右孩子指针域 }BiTNode, *BiTree;
在二叉树的学习中,最重要的一个部分就是遍历。
遍历又分为四种:层次遍历(从上至下,从左至右)
#include<queue> //STL的queue队列使用头文件 void levelorder(Tree T) {//list leaves中层次遍历部分 queue<int> Q;//STL 队列,要加头文件 Q.push(T.root);//根节点入队,保证第一次循环非空 int k; bool flag = false;//用于判断输出的空格使用 while (!Q.empty()) {//当队列不为空 k = Q.front();//获取队头元素 Q.pop();//队头元素出队 if (T.data[k].lch == -1 && T.data[k].rch == -1) {//叶子结点 if (flag == false) { cout << k; flag = true; } else { cout << " " << k; } } else { if (T.data[k].lch != -1) { Q.push(T.data[k].lch); } if (T.data[k].rch != -1) { Q.push(T.data[k].rch); } } } }
先序遍历(根结点-左-右)
void PreOrderTraverse(BiTree T) {//T是指针,指向该层次的根结点 if(T != NULL) { cout << T->data;//访问根结点 //递归 PreOrderTraverse(T->lchild);//遍历左子树 PreOrderTraverse(T->rchild);//遍历右子树 } }
中序遍历(左-根-右)
void inorder(BiTree T)//只是遍历不需要& {//中序遍历二叉树T的递归算法 if (T)///若二叉树非空 { //中序遍历第一步,遍历左子树 inorder(T->lchild); //第二部分,访问根节点 cout << T->data; //第三部分,遍历右子树 inorder(T->rchild); } }
后序遍历(左-右-根)
void postorder(BiTree T)//只是遍历不需要& {//后序遍历二叉树T的递归算法 if (T)///若二叉树非空 { //第一步,遍历左子树 inorder(T->lchild); //第二部分,遍历右子树 inorder(T->rchild); //第三部分,访问根节点 cout << T->data; } }
通过代码的对比,会发现,前中后序的实现区别在于,左右结点和根结点访问的顺序。我认为其中最难的是层次编写,需要多加练习。
除遍历外,还要创造、复制、计算深度等,也需要掌握,这些内容同样也利用了递归,所以说,树就是一种递归的结构。
二叉树只是树的一种,在做题时,我们也会遇到不是二叉树的情况。
在树的存储中,有双亲、孩子、孩子兄弟表示法。其中孩子兄弟表示法又可以成为二叉树表示法,它可以将树用类似二叉树的形式存储,这样就方便了我们运用二叉树的知识去解决树的运用。
还学习了哈夫曼树,哈夫曼树又称最优树。靠根节点越近的权值越小。
二、心得体会
在完成作业和小组协作时,发现了自己的思维有着局限性,缺少了能够完全独立思考的能力,不利于接下来的学习。在代码实现的过程中,虽然没有完全自己独立完成,但是也能够用自己的思路去解题,而不是轻易放弃。虽然说思路可能不通,但我认为,这是一个过程,不可能一下子就成功,虽有些气馁但是也很开心。小组合作后,看了组长发的其他小组的完成代码,对比思路会发现,别人的总是很简便,没有复杂化。在代码能力不足的情况下,我在解题时总是容易将题目复杂化,这就更加加大了代码的实现难度。
3、目标
虽然这一章的题目有些难,但是有自己尝试去独立完成。
接下来希望能够继续保持,不要轻易地放弃。