数据结构学习第十三天

09:44:07 2019-08-28

学习

昨天做了 课程要求的 PTA的三道题 

基本上涉及了 树的建立 以及树的遍历

今天把昨天 学到的树的遍历 的非递归 实现了一下

写的过程也不是特别顺利 看来 知道代码怎么一回事 和 把代码写出 还是有很大区别的

利用 前序中序后序遍历 以及 层序遍历 输出该树

  1 #define _CRT_SECURE_NO_WARNINGS    //vs中scanf为不安全的函数 要使用 得加上这句话
  2 #include<stdio.h>
  3 #define Size 10
  4 struct TreeNode
  5 {
  6     char Data;
  7     int LeftChild;
  8     int RightChild;
  9     int times;   //为例后序遍历的非递归使用
 10 }Tree[10];
 11 int Stack[10];
 12 int STop;   //栈顶下标
 13 void Push(int Num)
 14 {
 15     Stack[STop++] = Num;
 16 }
 17 int Pop()
 18 {
 19     return Stack[--STop];
 20 }
 21 int IsEmpty()
 22 {
 23     return !STop;
 24 }
 25 
 26 int Queue[10];
 27 int Front = 1;
 28 int Rear = 0;
 29 int QSize;
 30 int Succ(int num)    //判断是否越界
 31 {
 32     if (num < Size)
 33         return num;
 34     else
 35         return 0;
 36 }
 37 void EnQueue(int num)
 38 {
 39     Rear = Succ(Rear+1);
 40     Queue[Rear] =num;
 41     QSize++;
 42 }
 43 int DeQueue()
 44 {
 45     int num = Queue[Front];
 46     Front = Succ(Front+1);
 47     QSize--;
 48     return num;
 49 }
 50 
 51 //非递归实现遍历 
 52 //前序中序后序遍历 的非递归做法都是利用栈    因为 前序中序后序的访问顺序是一样的
 53 void InOrderTraversal(int Bt);  //中序遍历  
 54 void PreOrderTraversal(int Bt); //先序遍历
 55 void PostOrderTraversal(int Bt); //后序遍历
 56 
 57 //层序遍历的做法是利用 队列
 58 void LevelOrderTraversal(int Bt); //层序遍历
 59 
 60 void InOrderTraversal(int Bt)
 61 {
 62     while (Bt!=-1||!IsEmpty())  //空树不输出 如果栈内还有元素 得输出
 63     {
 64         while (Bt != -1)
 65         {
 66             Push(Bt);                     //第一次遇见
 67             Bt = Tree[Bt].LeftChild;
 68         }
 69         if (!IsEmpty())
 70         {
 71             int T = Pop();                //第二次遇见 输出
 72             printf("%c ", Tree[T].Data);
 73             Bt = Tree[T].RightChild;   //转向右节点
 74         }
 75     }
 76 }
 77 void PreOrderTraversal(int Bt)
 78 {
 79     while (Bt != -1 || !IsEmpty())  //空树不输出 如果栈内还有元素 得输出
 80     {
 81         while (Bt != -1)
 82         {
 83             Push(Bt);                     //第一次遇见 输出
 84             printf("%c ", Tree[Bt].Data);
 85             Bt = Tree[Bt].LeftChild;
 86         }
 87         if (!IsEmpty())
 88         {
 89             int T = Pop();                
 90             Bt = Tree[T].RightChild;     //转向右节点
 91         }
 92     }
 93 }
 94 void PostOrderTraversal(int Bt)
 95 {
 96     while (Bt != -1 || !IsEmpty())  //空树不输出 如果栈内还有元素 得输出
 97     {
 98         while (Bt != -1)
 99         {
100             Push(Bt);                     //第一次遇见 
101             Tree[Bt].times++;
102             Bt = Tree[Bt].LeftChild;
103         }
104         if (!IsEmpty())
105         {
106             int T = Pop();
107             if (Tree[T].times == 2)            //判断是否第三次遇见
108                 printf("%c ", Tree[T].Data);   //第三次遇见 输出
109             else
110             {
111                 Push(T);
112                 Tree[T].times++;
113                 Bt = Tree[T].RightChild;    //第二次遇见 转向右孩子
114             }
115         }
116     }
117 }
118 
119 void LevelOrderTraversal(int Bt)
120 {
121     if (Bt == -1)  //空树
122         return;
123     EnQueue(Bt);    //首先必须进队 根节点
124     while (QSize)     //队列不为空 
125     {
126         int T= DeQueue();
127         printf("%c ", Tree[T].Data);
128         if (Tree[T].LeftChild != -1) EnQueue(Tree[T].LeftChild);
129         if (Tree[T].RightChild != -1)EnQueue(Tree[T].RightChild);
130     }
131 }
132 int Convert(char num)     //将字符转换为数字
133 {
134     if (num == '-')
135         return -1;
136     else
137         return num - '0';
138 }
139 int BuildTree()   //利用 数组建树
140 {
141     int Root=-1;   //记录根节点
142     int N=0;     
143     int Check[10] = { 0 };  //用来判断根节点的位置
144     scanf("%d\n", &N);
145     for(int i=0;i<N;i++)
146     {
147         char Data, Num1, Num2;
148         scanf("%c %c %c\n", &Data, &Num1, &Num2);
149         Tree[i].Data = Data;
150         Tree[i].LeftChild = Convert(Num1);
151         Tree[i].RightChild = Convert(Num2);
152         if (Tree[i].LeftChild != -1)Check[Tree[i].LeftChild] = 1;
153         if (Tree[i].RightChild != -1)Check[Tree[i].RightChild] = 1;
154     }
155     for (int i = 0; i < N; i++)
156     {
157         if (!Check[i])
158             Root = i;
159     }
160     return Root;
161 }
162 int main()
163 {
164     int Tree;
165     Tree = BuildTree();
166     InOrderTraversal(Tree); printf("\n");//中序遍历
167     PreOrderTraversal(Tree); printf("\n");  //先序遍历
168     PostOrderTraversal(Tree); printf("\n"); //后序遍历
169     LevelOrderTraversal(Tree); //层次遍历
170 }
View Code

输入数据:

8
A 1 2
B 3 4
C 5 -
D - -
E 6 -
G 7 -
F - -
H - -

 输出结果:

结果正确

今天了解了下 二叉搜索树 还学了平衡二叉树(AVL)

然后又被题虐。。

PAT 第9题 判断是否为同一颗 二叉搜索树

 1 #define _CRT_SECURE_NO_WARNINGS    //vs中scanf为不安全的函数 要使用 得加上这句话
 2 #include<stdio.h>
 3 #include<malloc.h>
 4 typedef struct TNode* BinTree;
 5 typedef BinTree Position;
 6 struct TNode
 7 {
 8     int Element;
 9     BinTree Left;
10     BinTree Right;
11 };
12 BinTree Trees[10];
13 
14 BinTree Insert(int Element, BinTree BST)
15 {
16     if (!BST)       //BST为空 生成该节点 并且返回
17     {
18         BST = (Position)malloc(sizeof(struct TNode));
19         BST->Element = Element; BST->Left = NULL; BST->Right = NULL;
20     }
21     else
22         if (Element < BST->Element)
23             BST->Left = Insert(Element, BST->Left);   //递归插入左子树
24         else if (BST->Element < Element)
25             BST->Right = Insert(Element, BST->Right);  //递归插入右子树
26     return BST;
27 }
28 void MakeTrees(int N, int i)
29 {
30     int num;
31     scanf("%d", &num);
32     Trees[i] = (BinTree)malloc(sizeof(struct TNode));
33     Trees[i]->Element = num;
34     Trees[i]->Left = Trees[i]->Right = NULL;
35     for (int j = 0; j < N - 1; j++)
36     {
37         scanf("%d", &num);
38         Trees[i] = Insert(num, Trees[i]);
39     }
40     getchar();
41 }
42 int Charge(BinTree T, BinTree Tree)   //判断2个树是否相同
43 {
44     if (T == NULL && Tree == NULL)   //空树 一定相同
45         return 1;
46     if (T->Element != Tree->Element)  //判断节点处元素是否相同
47         return 0;
48     else
49         return Charge(T->Left, Tree->Left) && Charge(T->Right, Tree->Right);  //递归判断2个子树
50 }
51 int main()
52 {
53     int N;
54     int L;
55     scanf("%d", &N);
56     while (N)
57     {
58         scanf("%d\n", &L);
59         for (int i = 0; i <= L; i++)
60             MakeTrees(N, i);
61         for (int i = 1; i <= L; i++)
62             if (Charge(Trees[0], Trees[i]))
63                 printf("Yes\n");
64             else
65                 printf("No\n");
66         scanf("%d", &N);
67     }
68 }
View Code

PAT 第10题 找平衡二叉树的根节点

  1 #define _CRT_SECURE_NO_WARNINGS    //vs中scanf为不安全的函数 要使用 得加上这句话
  2 #include<stdio.h>
  3 #include<malloc.h>
  4 typedef struct TNode* BinTree;
  5 typedef BinTree Position;
  6 struct TNode
  7 {
  8     int Element;
  9     BinTree Left;
 10     BinTree Right;
 11     int Heigth; //高度
 12 };
 13 int GetHeight(BinTree T)
 14 {
 15     if (!T)
 16         return -1;
 17     else
 18         return T->Heigth;
 19 }
 20 
 21 int Max(int a, int b)
 22 {
 23     return (a > b) ? a : b;
 24 }
 25 BinTree NewNode(int Element)
 26 {
 27     BinTree T = (BinTree)malloc(sizeof(struct TNode));
 28     T->Element = Element;
 29     T->Left = NULL;
 30     T->Right = NULL;
 31     T->Heigth = 0;
 32     return T;
 33 }
 34 BinTree SingleLeftRotation(BinTree T)
 35 {
 36     BinTree TL = T->Left;
 37     T->Left = TL->Right;
 38     TL->Right = T;
 39     T->Heigth = Max(GetHeight(T->Left), GetHeight(T->Right)) + 1;
 40     TL->Heigth = Max(GetHeight(TL->Left),T->Heigth)+1;
 41     return TL;
 42 }
 43 BinTree SingleRightRotation(BinTree T)
 44 {
 45     BinTree TR = T->Right;
 46     T->Right = TR->Left;
 47     TR->Left = T;
 48     T->Heigth = Max(GetHeight(T->Left),GetHeight(T->Right))+1;
 49     TR->Heigth =Max(GetHeight(TR->Right),T->Heigth)+1;
 50     return TR;
 51 }
 52 BinTree DoubleLeftRightRotation(BinTree T)
 53 { //先做一次右单旋 再做一次左单旋
 54     T->Left = SingleRightRotation(T->Left);
 55     return SingleLeftRotation(T);
 56 }
 57 BinTree DoubleRightLeftRotation(BinTree T)
 58 {//先做一次左旋 再做一次右旋
 59     T->Right = SingleLeftRotation(T->Right);
 60     return SingleRightRotation(T);
 61 }
 62 BinTree Insert(int Element, BinTree BST)
 63 {
 64     if (!BST)       //BST为空 生成该节点 并且返回
 65         BST = NewNode(Element);
 66     else
 67         if (Element < BST->Element)
 68         {
 69             BST->Left = Insert(Element, BST->Left);   //递归插入左子树
 70             if (GetHeight(BST->Left) - GetHeight(BST->Right) == 2)    //判断是否需要进行旋转
 71                 if (Element < BST->Left->Element)    //左单旋
 72                     BST=SingleLeftRotation(BST);
 73                 else
 74                     BST=DoubleLeftRightRotation(BST);     //左-右双旋
 75         }
 76         else if (BST->Element < Element)
 77         {
 78             BST->Right = Insert(Element, BST->Right);  //递归插入右子树
 79             if (GetHeight(BST->Left) - GetHeight(BST->Right) == -2)
 80                 if (Element > BST->Right->Element)    //右单旋
 81                     BST=SingleRightRotation(BST);
 82                 else
 83                     BST=DoubleRightLeftRotation(BST);    //右-左双旋
 84         }
 85     BST->Heigth = Max(GetHeight(BST->Left), GetHeight(BST->Right)) + 1;
 86     return BST;
 87 }
 88 BinTree MakeTree()
 89 {
 90     int N;
 91     scanf("%d",&N);
 92     int num;    
 93     scanf("%d", &num);
 94     BinTree T = NewNode(num);
 95     for (int i = 1; i < N; i++)
 96     {
 97         scanf("%d", &num);
 98         T=Insert(num, T);
 99     }
100     return T;
101 }
102 int main()
103 {
104     BinTree Root = MakeTree();
105     printf("%d", Root->Element);
106 }
View Code

首先 我发现了 我刚开始数据输入就不对 格式什么都不匹配 再者 也想不出什么算法来。。。

猜你喜欢

转载自www.cnblogs.com/57one/p/11423218.html