数据结构基础_二叉树
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构基础_二叉树相关的知识,希望对你有一定的参考价值。
二叉树
二叉树(Binary Tree)的递归定义:二叉树要么为空,要么由根节点(root)、左子树(left subtree)和右子树(right subtree)组成。
小球落下
题目:一棵二叉树,初始开关关闭。当小球到达一个内节点时,如果该节点上的开关关闭,则往左走,否则往右走,直到走到叶结点。
输入:
4 2
3 4
10 1
2 2
8 128
16 12345
输出:
12
7
512
3
255
36358
思路:只需看小球的编号的奇偶性,就能知道它是最终在哪棵树中。对于那些落入根节点左子树的小球来说,秩序知道该小球是第几个落在根的左子树里,就可以知道他下一步是往左还是往右。
1 #include <stdio.h>
2 #include<stdio.h>
3 const int MAXD=20;
4 int main() {
5 int D,I;
6 while(scanf("%d%d",&D,&I)!=EOF){
7 int k=1;
8 for(int i=0;i<D-1;i++){
9 if(I%2==1){k=k*2;I=(I+1)/2;}
10 else {k=k*2+1;I=I/2;}
11 }
12 printf("%d\n",k);
13 }
14 return 0;
15 }
层次遍历
题目:输入一棵二叉树,你的任务是按从上到下,从左到右的顺序输出各个节点的值。如果从根节点到某个叶结点的路径上有的节点没有在输入中给出,或者给出了超过了一次,应当输出 -1。
节点个数不超过256.
输入:
(11,LL) (7,LLL) (8,R) (5,) (4,L) (13,RL) (2,LLR) (1,RRR) (4,RR) ()
(3,L) (4,R) ()
输出:
5 4 8 11 13 4 7 2 1
思路:采用动态结构,根据需要建立新的节点,然后把它们组织称一棵树。
六步:
- 二叉树的定义和操作。首先需要定义一个称为Node的数据类型,并且对应整棵二叉树的树根root。
- 每次需要一个Node时,都要用malloc函数申请内存,并返回一个未初始化的空间,把申请的新结点的操作封装到newnode函数中。
- 创建addonde函数,它按照序列行走,目标不存在是调用newnode来创建新结点。
- 接下来是释放一棵二叉树的代码。
- 编写输入部分和主函数。不停读入结点,如果在读到空括号之前文件结束,则返回0。这里两次调用了C语言的灵活性,可以把任意”指向字符的指针“看成是字符串,从该位置开始,直到字符‘0’。例如,读入字符”(11,LL)“,则&s[1]所对应的字符串是"11,LL)"。
- 输入和建树部分已经结束,接下来需要按照层次顺序遍历这棵树。我们使用一个队列来完成这个任务,初始时只有一个根节点,然后每次取出一个节点,就把它的左右儿子放进队。
sscanf(&s[1],"%d",&v);因为这句话多了个双引号,改的要死。最后面还是学长找出来的。
- 理解不透彻吧,sscanf第一个参数表示字符串(要读出来的),如果是数据就要引用,比如“10kk010”,如果是字符串就不用双引号,就不用双引号,就不用双引号!
- 第二个参数是格式规范,就是你要输入的下一个数据的类型,或者是你要输入对第一个参数的提取。比如要提取第一个0后面的数据就,"%*[^k]%s"。
- 第三个数据就是对应要输入的数据地址符号,或者buf缓冲区(要读进去的)。
1 #include <stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 const int MAXN=256; 5 char s[MAXN]; 6 int failed; 7 int n=0,ans[MAXN];//节点总数和输出队列 8 //二叉树的结点定义和操作。 9 //节点类型 10 typedef struct Tnode{ 11 int have_value;//是否被赋值过 12 int v;//结点值 13 struct Tnode *left,*right; 14 }Node; 15 Node* root;//二叉树根节点 16 //把申请的结点的操作封装到newnode 17 Node* newnode(){ 18 Node* u=(Node*) malloc(sizeof(Node)); 19 if(u!=NULL){ 20 u->have_value=0; 21 u->left=u->right=NULL; 22 } 23 return u; 24 } 25 //addnode函数,它按照移动序列走,目标不存在时调用newnode来创建新的节点。 26 void addnode(int v,char* s){ 27 int n=strlen(s); 28 Node* u=root;//从根节点往下走 29 for(int i=0;i<n;i++){ 30 if(s[i]==‘L‘){ 31 if(u->left==NULL) u->left=newnode();//节点不存在,建立新的节点 32 u=u->left;//往左走 33 } 34 else if(s[i]==‘R‘){ 35 if(u->right==NULL) u->right=newnode(); 36 u=u->right; 37 } 38 } 39 if(u->have_value)failed=1;//已经赋过值,表示输入有误 40 u->v=v; 41 u->have_value=1; 42 } 43 44 void remove_tree(Node *u){ 45 if(u==NULL) return; 46 remove_tree(u->left);//递归释放左子树 47 remove_tree(u->right);//递归释放右子树 48 free(u);//释放u节点本身的内存 49 } 50 //输入部分和主程序 51 int read_input(){ 52 failed=0; 53 remove_tree(root); 54 root=newnode(); 55 for(;;){ 56 if(scanf("%s",s)!=1)return 0;//整个输出结束 57 if(!strcmp(s,"()"))break;//读到结束标志,退出循环 58 int v; 59 sscanf(&s[1],"%d",&v); 60 addnode(v,strchr(s,‘,‘)+1); 61 } 62 return 1; 63 } 64 //接下来需要按照层次遍历的顺序遍历这棵树 65 int bfs(){ 66 int front=0,rear=1; 67 Node* q[MAXN]; 68 q[0]=root; 69 while(front<rear){ 70 Node* u=q[front++]; 71 if(!u->have_value) return 0;//有节点没有被赋值过,表明输入有误。 72 ans[n++]=u->v; 73 if(u->left!=NULL)q[rear++]=u->left; 74 if(u->right!=NULL)q[rear++]=u->right; 75 } 76 return 1; 77 } 78 79 80 81 82 int main() { 83 while(read_input()){ 84 if(bfs()==0||failed==1) printf("-1\n"); 85 else{ 86 for(int i=0;i<n;i++){ 87 printf("%d ",ans[i]); 88 } 89 printf("\n"); 90 } 91 } 92 return 0; 93 }
二叉树重建
题目:输入一棵二叉树的先序遍历和中序遍历序列,输出它的后序遍历序列。
输入:
DBACEGF ABCDEFG
BCAD CBAD
输出:
ACBFGED
CDAB
1 #include <stdio.h> 2 #include<string.h> 3 const int MAXN=1010; 4 char ans[MAXN],s1[MAXN],s2[MAXN]; 5 void build(int n,char *s1,char *s2,char *s){ 6 if(n<=0)return; 7 int p=strchr(s2,s1[0])-s2; 8 //s2代表字符的s2的起始地址的位置从0开始, 9 build(p,s1+1,s2,s);//递归左子树的后序遍历 10 build(n-p-1,s1+p+1,s2+p+1,s+p);//递归右子树的后序遍历 11 s[n-1]=s1[0];//把根节点添加到最后 12 } 13 int main() { 14 while(scanf("%s%s",s1,s2)!=EOF){ 15 int n=strlen(s1); 16 build(n,s1,s2,ans); 17 ans[n]=‘\0‘;//添加字符结束的标志 18 printf("%s\n",ans); 19 } 20 return 0; 21 }
以上是关于数据结构基础_二叉树的主要内容,如果未能解决你的问题,请参考以下文章