第五章 树与二叉树

这周学习了树和二叉树。

主要就是递归,之前一直不明白递归是什么,通过这几次课我了解的更详细,也体会到了递归的神奇之处。

来记录一些我从课堂上学到了知识吧

 

二叉树的课堂笔记
1,    返回值,先看函数要干嘛,如果是对内容进行操作类,无需结果回传
2,原型声明,直接copy函数定义那里,只不过形参括号内不用类型定义
Typedef struct Node{//结构体定义,链表的结点定义
ElemType data;
Struct node *lchild;
Struct node *rchild;
}Node,*Bitree;//都是代表二叉树的结点名称,区别就是Node *t之某个结点的指针,Bitree指头指针(或是说根节点)

Void PreOrder(Node*/Bitree  t)//t是一个根节点  (注意!在定义函数时,括号里的形参要有类型定义)
{
  If(t==NULL) return;(return用法?返回上层?
  cout << t->data << “ “;(输出根的数据,为什么记录的是用双引号
  PreOrder(t->lchild);
PreOrder(t->rchild);//用递归造树,(只对本层写正确逻辑,不考虑下层)
}
//函数说明:左孩子为空时,return退出当前函数,返回上层(递归),进行PreOrder(t->rchild)


void create (Bitree &t)//建立一棵空树,t指向根结点
                   //发现该树传不回去,说明是形参问题,但是t是指针,为什么会传不回去呢?但对t进行操作时,如果改变的是其直接空间,如操作(a),,只改变地址,不改变t的内容,如改变其间接空间,如(a[1],a[2])是不需要&)  
{//每建立一棵树,先读入,再判断是否#(为空树)
  ElemType x;//以X作为根结点的树
  cin >> x;
  if (x == ‘#’){//建立一颗空树
    t = NULL;//有指针就要赋初值
    return ;//强行中止函数执行
  }
  t == new Node;//为t分配像Node结构的空间
//操作的是间接空间
//形参不用再在函数内进行定义!!直接用
  t->data = x;//输入根结点x
  create(t->lchild);
create(t->rchild);

//一般操作先写主函数架构思路,再不断补充函数的操作
Int main()
{
  Bitree t ==NULL;//结构体Bitree直接用,形参在主函数中定义就够了!
  create( t );//创造读入树  注意在主函数中引用函数直接写函数名(形参)即可
  PreOrder( t );//读出树
  return 0;
}
课堂小笔记1

以及老师带我们打的深入虎穴的思路

1.      对树进行层次遍历
2.    门的编号1-N
3.    由编号得出可用数组
4.      二维数组表现树的存储关系,符合行号列号置一
5.    第二种
6.    10的5次*10 的5次,考虑稀疏矩
7.    可看为1维数组
8.    存储指针(单链表)
9.    先定义一个结构体(整数加指针)
10.    第二种,指针P后面带了一个数组P【0】,P【111.    P指针后面用new申请一个新数组空间
思路

再然后是作业啦,

 1 #include<iostream>
 2 #include<queue>
 3 using namespace std;
 4 
 5 typedef char ElemType;
 6 
 7 typedef struct Node{//结构体定义,链表的结点定义
 8 ElemType data;
 9 struct Node *lchild;
10 struct Node *rchild;
11 }Node,*Bitree;//都是代表二叉树的结点名称,区别就是Node *t之某个结点的指针,Bitree指头指针(或是说根节点)
12 
13 void levelOrderTraverse(Bitree t, int x)//t是一个根节点  //PreOrder函数用于遍历输出 (层次遍历) 
14 {
15   queue<int> q;
16   int m;
17   if(t==NULL) return;
18   if(t->lchild == NULL && t->rchild == NULL )
19   q.push(t->data);
20   while(!q.empty()){
21       m == q.front();
22       q.pop();
23       if(!q.empty())
24       cout << m <<" ";
25       else cout << m;
26     q.push(t[m].lch);//??t要用数组表示不然表示不出跳到下一个指针的方法 
27     q.push(t[m].rch);
28   }
29   //用递归造树,(只对本层写正确逻辑,不考虑下层)
30 }
31 //函数说明:左孩子为空时,return退出当前函数,返回上层(递归),进行PreOrder(t->rchild)
32 
33 int BulidTree(Bitree t)
34 {
35     
36     
37     bool check[100] = {false};
38     int n;
39     char x, y;
40     
41     cin >> n;
42     
43     for (int i=0; i<n; i++){
44         
45         cin >> x >> y;
46         
47         if(x!='-'){
48           t->lchild = x-'0';
49           check[t->lchild] = true;
50         }
51         else 
52           t->lchild = -1;
53           
54         if(y!='-'){
55           t->rchild = y-'0';
56           check[t->rchild] = true;
57         }
58         else
59           t->rchild = -1;
60     }
61     
62     for (int i=0; i<n; i++){
63         if(!check[i]) return i;
64     }
65 }
66 
67 /*void create (Bitree &t)//建立一棵树,并读入,t指向根结点
68 {//每建立一棵树,先读入,再判断是否-(为空树)//在输入树时顺便找根结点 
69   ElemType x;//以X作为根结点的树
70   cin >> x;
71   if (x == '-'){//根为空 
72     t = NULL;//有指针就要赋初值
73     return ;//强行中止函数执行
74   }
75   //x!='-';
76   t == new Node;//为t分配像Node结构的空间
77   t->data = x-'0';//输入根结点数字x
78   create(t->lchild);
79   create(t->rchild);
80 }
81 */
82 
83 int main()
84 {
85   int x; 
86   Bitree t;//不能Bitree t == NULL 
87   t == NULL;//结构体Bitree直接用,形参在主函数中定义就够了!
88   //create(t);//创造读入树  注意在主函数中引用函数直接写函数名(形参)即可
89   x == BulidTree(t);//找到根结点 
90   levelOrderTraverse(t, x);//读出树
91   return 0;
92 }
版本1

这个因为结点用的是指针,所以在如何把左孩子转化为下一个指针的时候出现了问题,暂时还没想到解决的办法,

于是我换成了用数组表示本结点的名字,这样就可以通过i来表示。

 1 #include<iostream>
 2 #include<queue>
 3  
 4 using namespace std;
 5 
 6 typedef struct{//树结点的类型定义 
 7     int lch;
 8     int rch;
 9 }node;
10 
11 int BulidTree(node t[]);
12 void levelOrderTraverse(node t[], int x); //层次遍历 
13 
14 
15 int main()
16 {    
17     node t[100];//??怎么可以直接node一个数组呢 
18     int x; 
19     
20     x = BulidTree(t);//找出了根节点x 
21     levelOrderTraverse(t, x);      //水平遍历并输出叶子结点  
22     return 0; 
23 }
24 
25 int BulidTree(node t[])//输入并查找根结点 
26 {
27     bool check[100] = {false};//判断根结点的标志 
28     int n;
29     char x, y;
30     
31     cin >> n;
32     
33     for (int i=0; i<n; i++){
34         
35         cin >> x >> y;//输入左孩子和右孩子 
36         
37         if(x!='-'){//如果孩子不为空 
38           t[i].lch = x-'0';//给孩子赋值 
39           check[t[i].lch] = true;//标志改为ture 
40         }
41         else 
42           t[i].lch = -1;//否则孩子为-1 
43           
44         if(y!='-'){
45           t[i].rch = y-'0';
46           check[t[i].rch] = true;
47         }
48         else
49           t[i].rch = -1;
50     }
51     
52     for (int i=0; i<n; i++){
53         if(!check[i]) return i;//返回根结点下标 
54     }
55 }
56     
57 void levelOrderTraverse(node t[], int x)
58 {//层次遍历t[x]为根结点的树t
59     int tmp;
60     queue<int> q;
61     q.push(x); //根结点所在下标入栈 
62     int flag = 0;    //用flag做判断第一个输出的指标 
63     while(!q.empty()){
64         tmp = q.front(); //记录队头元素 
65         q.pop();
66         flag++;
67         if(t[tmp].lch==-1 && t[tmp].rch==-1)//如果是叶子结点 ,输出 
68         {
69             if(flag == 0) cout << tmp;
70             else cout << " " << tmp;
71         }
72             q.push(t[tmp].lch);//如何做到层次遍历 
73             q.push(t[tmp].rch);
74         
75     } 
76 } 
版本2

这个版本也出现了一点问题,不知道哪里出错了,排错排的时间有点久,希望下次能加快发现错误的时间。

 

上周目标达成:因为假期出去玩的有点多,所以作业质量不是很好,但是改错的能力加强了,这点还是让人有感到成就感的,慢慢理解到了一些刚开始不懂得东西,比如自定义类型为什么要这样写之类的小问题。

本周目标:做到边打代码边写注释,而不是打完之后才写

继续认真复习,总结归纳

认真完成作业。

posted @ 2019-05-04 23:51  Y000  阅读(154)  评论(1编辑  收藏  举报