1【栈】LIFO或FILO表
栈按“先进先出”的规则进行操作,故称栈为操作受限的线性表。栈是限制在表的同一端进行插入和删除的线性表。允许插入、删除的这一端称为栈顶,另一固定端称为栈底。栈中没有元素时称为空栈。
由于栈是运算受限的线性表,所以有些操作在栈中就不允许,插入只能在栈顶进行,删除操作也只能在栈顶进行,而不允许在栈的其它任何位置进行插入和删除操作。所以栈上可进行的操作要比线性表少。
顺序栈:利用顺序存储结构实现的栈称为顺序栈。栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈顶的数据元素。
1 #define STACK_INITSIZE 8 2 #define STACK_INCREAMENT 2 3 typedef struct SqStack{ 4 ELemType *elem;//用elem指向该存储单元的初始地址 5 int top; //同时附设指针top指示栈顶的位置,始终在栈顶元素所在位置的后面那个位置 6 int stacksize;//用stacksize指示栈的当前可使用的最大容量 7 }SqStack; 8 //栈的初始化 9 int InitStack(Seqstack *s) 10 { 11 S->elem=(ElemType *)malloc(sizeof(ElemType)*STACK_INITSIZE); 12 if(!(S->elem)) 13 return ERROR; 14 S->stacksize=STACK_INITSIZE; 15 S->top=0; 16 return OK; 17 } 18 //栈的入栈操作 19 int Push(SeqStack *S,ElemType e) 20 { 21 ElemType *newbase,newspacesize; 22 if(S->top>=S->stacksize-1) 23 { 24 newspacesize=(S->stacksize+STACK_INCREAMENT)*sizeof(ELemType); 25 newbase=(ElemType*)realloc(S->elem,newspacesize); 26 if(!newbase) 27 return ERROR; 28 S->elem=newbase; 29 S->stacksize+=STACK_INCREAMENT; 30 } 31 S->elem[S->top]=e; 32 S->top++; 33 return OK; 34 } 35 //出栈操作 36 int pop(SeqStack *S,ElemType *e) 37 { 38 if(S->top<=0) 39 return ERROR; 40 *e=S->elem[S->top-1]; 41 S->top--; 42 return OK; 43 } 44 //取栈顶元素操作 45 int GetTop(SeqStack *S,ElemType *S) 46 { 47 if((S->top)<=0) 48 return ERROR; 49 *e=(*S).elem[S->top-1]; 50 return OK; 51 } 52 //判断栈是否为空 53 int StackEmpty(SeqStack *S) 54 { 55 if(S->top<=0) 56 return 1; 57 else 58 return 0; 59 } 60 //求栈的深度 61 int StackDepth(SeqStack *S) 62 { 63 return S->top; 64 } 65 //清空栈 66 int ClearStack(SeqStack *S) 67 { 68 return S->top; 69 return OK; 70 }
链栈:用链式存储结构实现,一般用带头结点单链表作为栈的结构。用链表的头部做栈顶是最方便的,则规定单链表的头结点这一端为栈顶,单链表的最后一个元素这一端为栈底。所以在链表中入栈和出栈操作只能在链表的头结点进行。
【下面具体代码】
顺序栈:
1 #define maxsize 100 2 typedef struct SqStack{ 3 int data[maxsize]; 4 int top; 5 }SqStack; 6 #include<stdio.h> 7 #include<stdlib.h> 8 #define maxsize 100 9 typedef struct SqStack{ 10 int data[maxsize]; 11 int top; 12 }SqStack; 13 //初始化顺序栈 14 void initSqStack(SqStack *st){ 15 st->top=-1; 16 } 17 //判断栈是否为空 18 int SqStackEmpty(SqStack *st){ 19 return (st->top==-1?1:0); 20 } 21 //进栈 22 int push(SqStack *st,int x){ 23 if(st->top==maxsize-1){ 24 return 0; 25 } 26 st->data[++st->top]=x; 27 return 1; 28 } 29 //出栈 30 int pop(SqStack *st,int *x){ 31 if(st->top ==-1){ 32 return 0; 33 } 34 *x=st->data[st->top--]; 35 return 1; 36 } 37 //打印栈元素 38 void printStack(SqStack *st){ 39 while(st->top !=-1){ 40 printf("栈元素:%d ",st->data[st->top--]); 41 } 42 } 43 void main(){ 44 int x; 45 SqStack st={{1,2,3,4},3}; 46 push(&st,5); 47 pop(&st,&x); 48 printf("出栈元素:%d ",x); 49 printStack(&st); 50 } 51 ---------------------
输出元素5 4 3 2 1
链栈:
1 typedef struct Lnode{ 2 int data; 3 struct Lnode *next; 4 }Lnode; 5 #include<stdio.h> 6 #include<stdlib.h> 7 typedef struct Lnode{ 8 int data; 9 struct Lnode *next; 10 }Lnode; 11 //初始化链栈 12 void initStack(Lnode *ln){ 13 ln=(Lnode *)malloc(sizeof(Lnode)); 14 ln->next=NULL; 15 } 16 //判断链栈是否为空 17 int StackEmpty(Lnode *ln){ 18 return (ln->next==NULL?1:0); 19 } 20 //进栈 21 void push(Lnode *ln,int x){ 22 Lnode *p; 23 p=(Lnode *)malloc(sizeof(Lnode)); 24 if(p ==NULL){ 25 printf("ERROR"); 26 exit(0); 27 } 28 p->next=NULL; 29 p->data=x; 30 p->next=ln->next; 31 ln->next=p; 32 } 33 //出栈 34 int pop(Lnode *ln,int *x){ 35 Lnode *p=ln->next; 36 if(p ==NULL){ 37 return 0; 38 } 39 *x=p->data; 40 ln->next=p->next; 41 free(p); 42 return 1; 43 } 44 void printStack(Lnode *ln){ 45 Lnode *p=ln->next; 46 while(p!=NULL){ 47 printf("%d ",p->data); 48 p=p->next; 49 } 50 } 51 void main(){ 52 Lnode ln; 53 int x; 54 initStack(&ln); 55 push(&ln,2); 56 push(&ln,3); 57 push(&ln,4); 58 push(&ln,5); 59 pop(&ln,&x); 60 printf("出栈元素为:%d ",x); 61 printStack(&ln); 62 } 63 结果: 64 ---------------------
输出结果:5 4 3 2
2【队列】FIFO表
队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。不能随意在队列的任意位置存取元素,新的元素每次都在队尾加入,老元素都在队头取出。
在使用顺序队列实现缓冲区时,队列的长度不能超过缓冲区的容量。
在队列的生存期中有三种情形:队列空、队列满、队列非空非满。在顺序队列情形中,队头和队尾指针沿同一方向移动。
【顺序队列】
1 #define MAXSIZE 100 //队列的最大容量 2 Typedef struct{ 3 QElemType elem[MAXSIZE]; //队列的存储空间 4 int rear,front; //队尾队头指针,front指向队头,rear始终指向最后一个元素的下一个位置 5 }SqQueue; 6 SqQueue Q; 7 若队列为空 rear=front 8 尾部插入时: v[rear]=a1;rear++; 9 头部删除:x=v[front];front--;
【循环队列】
1.图中有两个指针(其实就是两个整数型变量,因为在这里有指示作用,所以这里理解为指针)front、rear,一个指示队头,一个指示队尾。
2.rear和front互相追赶着,这个追赶过程就是队列添加和删除的过程,如果rear追到head说明队列满了,如果front追到rear说明队列为空。
1 #define MAXSIZE 100 //队列的最大容量 2 Typedef struct{ 3 QElemType *base; //动态分配存储空间 4 int front;//头指针,若队列不空,指向队列头元素 5 int rear; //队尾队头指针,若队列不空,指向队列尾元素的下一个位置 6 }SqQueue; 7 //空队列特征: 8 front=rear; 9 //队满特征: 10 front=(rear+1)%MAXQSIZE; 11 //队列长度: 12 L=(N+rear-front)%N; 13 //初始化: 14 q.front=q.rear=0; 15 //入队操作之前应判断队列是否为满: if((q.rear+1)%QUEUE_MAXSIZE==q.front); 16 return ERROR; 17 //插入动作: 18 q.base[q.rear]=e; 19 q.rear=(q.rear+1)%QUEUE_MAXSIZE; 20 //出队操作 21 e=q.base[q.front]; 22 q.front=(q.front+1)%QUEUE_MAXSIZE; 23 //求循环队列的元素个数 24 return (Q.rear-Q.front+MAXQSIZE)%MAXQSIZE;
【链队列】
1 typedef struct Qnoded{//结点类型 2 QElemType data; 3 struct Qnode *next; 4 }Qnode,*QueuePtr; 5 Typedef struct{//连队类型 6 QueuePtr front;//队头指针 7 QueuePtr rear; //队尾指针 8 }LinkQueue; 9 //入队操作: 10 int EnQueue(LinkQueue &Q,QELemType e) 11 { 12 QNode *p; 13 p=(QNode*)malloc(sizeof(Qnode)); 14 p->data=e; 15 p->next=NULL; 16 Q.rear->next=p; 17 Q.rear=p; 18 return OK; 19 } 20 //出队操作 21 int DeQueue(LinkQueue &Q,QElemType &e) 22 { 23 if(Q.rear==Q.rear) return ERROR; 24 p=Q.front->next; 25 e=p->data;//队头元素放入e中 26 Q.front->next=p->next; 27 if(Q.rear=p) 28 { 29 Q.rear=Q.front; //只有一个元素时,出队后队空,此时还要修改队尾指针 30 } 31 free(p); 32 rerturn OK; 33 }
注意:在循环队列进行删除和插入操作时,不需要比较和移动任何元素,只需要修改队尾和队头指针,并向队尾插入元素或从队头取出元素。
循环队列满的条件为(rear+1)%maxSize==front;
链队列空的条件是 front==NULL
3【链表】
链表:链表是通过一组任意的存储单元(可以连续也可以不连续)来存储线性表中的数据元素。根据线性表的逻辑定义,单链表的存储单元不仅能够存储元素,而且要求能表达元素与元素之间的线性关系。
链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) +指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。
【结点结构】
Head指针为单链表的头指针,指向链表的第一个结点。链表中的最后一个结点的指针域定义为空指针(NULL)。
【单链表的定义】
1 typedef struct Node{ 2 ElemType data; 3 struct Node *next; 4 }LNode,*LinkLIst;//LinkList指向LNode类型结点的指针类型 5 LinkList H;
.一、单链表的插入操作:
在结点p之前插入一个新的结点q:对于不带头结点的单链表,结点p的位置有所不同,插入操作有以下两种情况:
1)在链表的表头插入:
(1)创建一个新的结点q。
(2)将此结点的数据域赋值为e,并将它的next指针指向第一个结点,即L。
(3)将L修改为指向新的结点q。
操作示意图如下:
2)在链表的中间插入
(1)创建一个新的结点q。
(2)将此结点的数据域赋值为e,并将它的next指针指向p。
(3)查找到p的前驱结点pre。
(4)将pre的next指针指向新创建的结点q。
操作示意图如下:
【代码实现】
1 //不带头结点的单链表的插入操作 2 void LinkedListInertQE1(LinkedList L, LinkedList p, ElemType e) 3 { 4 q=(LNode *)malloc(sizeof(LNode)); //创建一个新的结点q 5 if(q==NULL) 6 { 7 printf("申请空间失败!"); 8 exit(0); 9 } 10 q->data=e; 11 12 if(p==L) //在表头插入 13 { 14 q->next=L; 15 L=q; 16 } 17 else //在表的中间进行插入 18 { 19 pre=L; 20 while((pre!=NULL)&&(pre->next!=p)) //寻找p的前驱 21 pre=pre->next; 22 23 q->next=pre->next; 24 pre->next=q; 25 } 26 } 27 28 //带头结点的单链表的插入操作 29 void LinkedListInertQE2(LinkedList L, LinkedList p, ElemType e) 30 { 31 q=(LNode *)malloc(sizeof(LNode)); //创建一个新的结点q 32 if(q==NULL) 33 { 34 printf("申请空间失败!"); 35 exit(0); 36 } 37 q->data=e; 38 39 //插入新的结点 40 pre=L; 41 while((pre!=NULL)&&(pre->next!=p)) //寻找p的前驱 42 pre=pre->next; 43 44 q->next=pre->next; 45 pre->next=q; 46 }
二、.单链表的删除操作
删除链表中的某个元素e,如果e在链表中出现不止一次,将删除第一次出现的e,否则什么也不做。
用p找到元素e所在的结点:
1)p是链表中的第一个结点
(1)将L指向p->next。
(2)释放p。
示意图如下:
2)p是链表中的其他结点
(1)找到p的前驱结点pre。
(2)将pre->next指向p->next。
(3)释放p。
1 //不带头结点的单链表的删除操作 2 void LinkedListDeleteQE1(LinkedList L, LinkedList p, ElemType e) 3 { 4 pre=L; 5 while((pre!=NULL)&&(pre->next->data!=e)) //查找元素e的前驱 6 pre=pre->next; 7 p=pre->next; 8 9 if(p!=NULL) //找到需要删除的结点 10 { 11 if(p==L) //删除的是第一个结点 12 L=p->next; 13 else //删除的是其他结点 14 pre->next=p->next; 15 free(p); 16 } 17 } 18 //带头结点的单链表的删除操作 19 void LinkedListDeleteQE2(LinkedList L, LinkedList p, ElemType e) 20 { 21 pre=L; 22 while((pre!=NULL)&&(pre->next->data!=e)) //查找元素e的前驱 23 pre=pre->next; 24 p=pre->next; 25 26 if(p!=NULL) //找到需要删除的结点 27 { 28 pre->next=p->next; 29 free(p); 30 } 31 }
三、单链表的创建操作
单链表的创建方法有两种:头插法和尾插法。
头插法是将新增结点插入第一个结点之前,示意图如下
:
尾插法是将新增结点插入最后一个结点之后,示意图如下:
1 //用头插法创建带头结点的单链表 2 void LinkedListCreateHeadL(LinkedList L, ElemType a[n]) 3 { 4 L=(LNode *)malloc(sizeof(LNode)); 5 if(L==NULL) 6 { 7 printf("申请空间失败!"); 8 exit(0); 9 } 10 L->next=NULL; 11 12 for(i=0; i<n; i++) 13 { 14 p=(LNode *)malloc(sizeof(LNode)); 15 if(p==NULL) 16 { 17 printf("申请空间失败!"); 18 exit(0); 19 } 20 21 p->data=a[i]; 22 p->next=L->next; 23 L->next=p; 24 } 25 } 26 //用尾插法创建带头结点的单链表 27 void LinkedListCreateTailL(LinkedList L, ElemType a[n]) 28 { 29 L=(LNode *)malloc(sizeof(LNode)); 30 if(L==NULL) 31 { 32 printf("申请空间失败!"); 33 exit(0); 34 } 35 L->next=NULL; 36 tail=L; //设置尾指针,方便插入 37 38 for(j=0; j<n; j++) 39 { 40 p=(LNode *)malloc(sizeof(LNode)); 41 if(p==NULL) 42 { 43 printf("申请空间失败!"); 44 exit(0); 45 } 46 47 p->data=a[j]; 48 p->next=NULL; 49 tail->next=p; 50 tail=p; 51 } 52 }
四、链表的排序
思想:本质为边遍历,边创建新链表。每次遍历旧链表,取其中的最小值并记录其指针,然后从旧链表中把该结点删除掉,然后创建一个新结点保存该指针,以便链接一个新链。
【目标代码】
1 struct Student *creatlinklist() 2 { 3 struct Student *head; 4 struct Student *p; 5 struct Student *ptail; 6 int n; 7 n=0; 8 head=NULL; 9 ////////////// 10 p=(struct Student *)malloc(sizeof(struct Student)); 11 printf("请输入姓名和java成绩:"); 12 scanf("%s%lf",p->name,&p->java); 13 while(p->java!=0) 14 { 15 if(n==0) 16 { 17 head=p; 18 ptail=p; 19 n++; 20 } 21 else 22 { 23 ptail->next=p; 24 ptail=p; 25 n++; 26 } 27 p=(struct Student *)malloc(sizeof(struct Student)); 28 printf("请输入姓名和java成绩:"); 29 scanf("%s%lf",p->name,&p->java); 30 } 31 if(head!=NULL) 32 ptail->next=NULL; 33 return head; 34 }
【考试代码】
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 struct Student 5 { 6 char name[20]; /*字符型学生姓名*/ 7 double java; /*双精度实型Java成绩*/ 8 struct Student *next; /*用与构建连表指向下一结点*/ 9 };
//动态创建链表 10 struct Student *creatlinklist() 11 { 12 struct Student *head; 13 struct Student *p; 14 struct Student *ptail; 15 int n; 16 n=0; 17 head=NULL; 18 ////////////// 19 p=(struct Student *)malloc(sizeof(struct Student)); 20 printf("请输入姓名和java成绩:"); 21 scanf("%s%lf",p->name,&p->java); 22 while(p->java!=0) 23 { 24 if(n==0) 25 { 26 head=p; 27 ptail=p; 28 n++; 29 } 30 else 31 { 32 ptail->next=p; 33 ptail=p; 34 n++; 35 } 36 p=(struct Student *)malloc(sizeof(struct Student)); 37 printf("请输入姓名和java成绩:"); 38 scanf("%s%lf",p->name,&p->java); 39 } 40 if(head!=NULL) 41 ptail->next=NULL; 42 return head; 43 } 44 //输出链表 45 void print_linklist(struct Student *head) 46 { 47 struct Student *pi; 48 if(head==NULL) 49 printf("该链表是空链表! "); 50 else 51 { 52 printf("姓名 java成绩 "); 53 for(pi=head;pi!=NULL;pi=pi->next) 54 printf("%s %lf ",pi->name,pi->java); 55 } 56 }
//查找链表 57 struct Student * search_linklist_by_name(struct Student *head,char name[]) 58 { 59 struct Student *pi,*ploc; 60 struct Student *phead,*ptail; 61 int n; 62 //////////////////////////// 63 phead=NULL; 64 n=0; 65 /////////////////////////// 66 for(pi=head;pi!=NULL;pi=pi->next) 67 { 68 if(strcmp(pi->name,name)==0) 69 { 70 ploc=(struct Student *)malloc(sizeof(struct Student)); 71 strcpy(ploc->name,pi->name); 72 ploc->java=pi->java; 73 if(n==0) 74 { 75 phead=ploc; 76 ptail=ploc; 77 n++; 78 } 79 else 80 { 81 ptail->next=ploc; 82 ptail=ploc; 83 n++; 84 } 85 } 86 } 87 if(phead!=NULL) 88 ptail->next=NULL; 89 ////////////////////////// 90 return phead; 91 92 }
//删除链表 93 struct Student *delete_linklist_by_name_single(struct Student *head,char name[]) 94 { 95 struct Student *ploc,*ploc0; 96 struct Student *pi; 97 int flag; 98 flag=0; 99 if(head==NULL) 100 { 101 printf("空链表! "); 102 exit(0); 103 } 104 if(strcmp(head->name,name)==0) 105 { 106 ploc=head; 107 head=head->next; 108 free(ploc); 109 flag=1; 110 } 111 else 112 { 113 for(pi=head;pi->next!=NULL;pi=pi->next) 114 { 115 if(strcmp(pi->next->name,name)==0) 116 { 117 ploc=pi->next; 118 ploc0=pi; 119 ploc0->next=ploc->next; 120 free(ploc); 121 flag=1; 122 break; 123 } 124 } 125 } 126 if(flag==0) 127 { 128 printf("查无此人! "); 129 } 130 return head; 131 } 132 133 int count_linklist_node(struct Student *head) 134 { 135 struct Student *pi; 136 int count=0; 137 for(pi=head;pi!=NULL;pi=pi->next) 138 { 139 count++; 140 } 141 return count; 142 } 143 struct Student * move_linklist(struct Student *head,int n) 144 { 145 struct Student *pi,*ploc; 146 int i; 147 i=0; 148 ploc=NULL; 149 for(pi=head;pi!=NULL;pi=pi->next) 150 { 151 i++; 152 if(i==n) 153 { 154 ploc=pi; 155 break; 156 } 157 } 158 return ploc; 159 }
//插入链表 160 struct Student * insert_linklist_by_location(struct Student *head,struct Student *p,int n)////该将p指针指向的结点插入到链表的第n个结点位置上 161 { 162 struct Student *pt,*ptail; 163 struct Student *ploc,*ploc0; 164 int count; 165 count=count_linklist_node(head); 166 if(p->java==0) 167 { 168 printf("java成绩为0的节点不能插入链表! "); 169 exit(0); 170 } 171 ///////////////////////// 172 if(n<=0||n>=count+2) 173 { 174 printf("插入位置有误! "); 175 exit(0); 176 } 177 ///////////////////////// 178 if(n==1) 179 { 180 pt=head; 181 head=p; 182 p->next=pt; 183 } 184 else 185 { 186 if(n==count+1) 187 { 188 ptail=move_linklist(head,count); 189 ptail->next=p; 190 p->next=NULL; 191 } 192 else 193 { 194 ploc0=move_linklist(head,n-1); 195 ploc=move_linklist(head,n); 196 ploc0->next=p; 197 p->next=ploc; 198 } 199 } 200 return head; 201 }
//链表排序 202 struct Student *select_sort_linklist_by_java(struct Student *head)//断链,重新创建新的有序链表 203 { 204 struct Student *phead,*ptail; 205 struct Student *pmin,*pmin0; 206 struct Student *pi; 207 int n; 208 phead=NULL; 209 n=0; 210 while(head!=NULL) 211 { 212 ///////////////////////////////第一部分,遍历当前无序链表(head所指向),找到其中java最小值节点的地址(pmin)以及相应的前驱节点地址(pmin0) 213 pmin=head; 214 for(pi=head;pi->next!=NULL;pi=pi->next) 215 { 216 if(pi->next->java<=pmin->java) 217 { 218 pmin=pi->next; 219 pmin0=pi; 220 } 221 } 222 //////////////////////////////第二部分,通过第一部分找到的java最小值节点的地址(pmin)以及相应的前驱节点地址(pmin0),对pmin指向的节点进行脱离无序链表操作,脱离分为两种情况:(1)当前最小java值节点在表头情况,(2)当前最小java值节点在表中情况 223 if(pmin==head) 224 { 225 head=head->next; 226 } 227 else 228 { 229 pmin0->next=pmin->next; 230 } 231 /////////////////////////////第三部分,将第二部分脱离出的pmin所指向的当前最小java值节点,依次挂到新的有序链表(phead所指向)中,这个过程类似于链表的动态创建。 232 if(n==0) 233 { 234 phead=pmin; 235 ptail=pmin; 236 n++; 237 } 238 else 239 { 240 ptail->next=pmin; 241 ptail=pmin; 242 n++; 243 } 244 } 245 if(phead!=NULL) 246 ptail->next=NULL; 247 return phead; 248 } 249 /////////////////////////////// 250 int main() 251 { 252 struct Student*head; 253 head=creatlinklist(); 254 printf("原来链表的数据为: "); 255 print_linklist(head); 256 head=select_sort_linklist_by_java(head); 257 printf("按照链表的java成绩排序后的链表数据为: "); 258 print_linklist(head); 259 return 0; 260 }
4【二叉树】
二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。
二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。
二叉树的第i层至多有2^{i-1}个结点;深度为k的二叉树至多有2^k-1个结点;对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点数为n2,则n0=n2+1。 一棵深度为k,且有2^k-1个节点称之为满二叉树。
包含n个结点的二叉树的高度至少为(log2n)+1
树的遍历:

- 先序遍历:从根节点开始,先遍历左子树,然后遍历右子树,在遍历子树的时候,依旧按照从根节点遍历左右子树的原则遍历(A,B,D,E,C,F)
- 中序遍历:从最左的叶子节点开始,先遍历左节点,然后根节点,再右节点(D,B,E,A,F,C)
- 后序遍历:从最左的叶子节点开始,先遍历左节点,然后右节点,再跟节点(D,E,B,F,C,A)
【代码实现】
#include"stdio.h" #include<stdlib.h> //创建一个结构体,使用一个二叉链表创建,其中包括数据域,左孩子指针域和右孩子指针域 typedef struct BiTNode{ char data; struct BiTNode *Lchild,*Rchild; }BiTNode,*BiTree; //动态创建一个二叉树 void CreatBiTree(BiTree *T){ char c; scanf("%c",&c); //输入一串数据,如果输入有值,则马上创建一个结点,若为空格,则不创建,回溯 if(c==' ') *T=NULL; else{ //动态创建结点 *T=(BiTNode*)malloc(sizeof(BiTNode)); //当前结点的数据域为输入的数据 (*T)->data=c; //递归创建左子树和递归创建右子树 CreatBiTree(&((*T)->Lchild)); CreatBiTree(&((*T)->Rchild)); } } //二叉树的遍历(先序遍历)根左右 /* 中序遍历:左根右 后序遍历:左右根 */ void PreOrderTraverse(BiTree T){ if(T){ printf("%C ",T->data); if(!T->Lchild){ printf("NULL "); } else{ printf("%d ",T->Lchild); } if(!T->Rchild){ printf("NULL "); } else{ printf("%d ",T->Rchild); } printf(" "); PreOrderTraverse(T->Lchild); PreOrderTraverse(T->Rchild); } } int main(){ BiTree T=NULL; CreatBiTree(&T); PreOrderTraverse(T); printf(" "); return 0; }
对于上图的测试结果为: