二叉树
二叉树(Binary tree)是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。二叉树特点是每个节点最多只能有两棵子树,且有左右之分 。
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,一个元素也称作一个节点 。

头函数及结构体
#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>
#define QUEUE_SIZE 5
/*
* 二叉树节点
*/
typedef struct BTNode{
char element;
struct BTNode* left;
struct BTNode* right;
}BTNode, *BTNodePtr;
/*
* 存储地址的队列
*/
typedef struct BTNodePtrQueue{
BTNodePtr* nodePtrs;
int front;
int rear;
}BTNodePtrQueue, *QueuePtr;
初始化队列操作
/*
* 初始化队列
*/
QueuePtr initQueue(){
QueuePtr resultQueuePtr=(QueuePtr)malloc(sizeof(struct BTNodePtrQueue));
resultQueuePtr->nodePtrs=(BTNodePtr*)malloc(QUEUE_SIZE*sizeof(BTNodePtr));
resultQueuePtr->front=0;
resultQueuePtr->rear=1;
return resultQueuePtr;
}
/*
* 判断队列是否为空
*/
bool isQueueEmpty(QueuePtr paraQueuePtr){
if((paraQueuePtr->front+1)%QUEUE_SIZE==paraQueuePtr->rear){
return true;
}
return false;
}
/*
* 将一个元素加入队列
*/
void enqueue(QueuePtr paraQueuePtr, BTNodePtr paraBTNodePtr){
printf("front = %d, rear = %d.\r\n",paraQueuePtr->front, paraQueuePtr->rear);
if((paraQueuePtr->rear+1)%QUEUE_SIZE==paraQueuePtr->front%QUEUE_SIZE){
printf("Error, trying to enqueue %c. queue full.\r\n",paraBTNodePtr->element);
return;
}
paraQueuePtr->nodePtrs[paraQueuePtr->rear]=paraBTNodePtr;
paraQueuePtr->rear=(paraQueuePtr->rear+1)%QUEUE_SIZE;
printf("enqueue %c ends.\r\n",paraBTNodePtr->element);
}
/*
* 从队列中删除一个元素
*/
BTNodePtr dequeue(QueuePtr paraQueuePtr){
if(isQueueEmpty(paraQueuePtr)){
printf("Error, empty queue.\r\n");
return NULL;
}
paraQueuePtr->front=(paraQueuePtr->front+1)%QUEUE_SIZE;
printf("dequeue %c ends.\r\n",paraQueuePtr->nodePtrs[paraQueuePtr->front]->element);
return paraQueuePtr->nodePtrs[paraQueuePtr->front];
}
创建单个节点及二叉树
/*
* 用给定的字符创建一个BTNode的节点
*/
BTNodePtr constructBTNode(char paraChar){
BTNodePtr resultPtr=(BTNodePtr)malloc(sizeof(BTNode));
resultPtr->element=paraChar;
resultPtr->left=NULL;
resultPtr->right=NULL;
return resultPtr;
}
/*
* 用给定的字符串创建一个二叉树
*/
BTNodePtr stringToBTree(char* paraString){
int i=0;
char ch;
// 用队列来管理指针
QueuePtr tempQueuePtr=initQueue();
BTNodePtr resultHeader;
BTNodePtr tempParent, tempLeftChild, tempRightChild;
ch=paraString[i];
resultHeader=constructBTNode(ch);
enqueue(tempQueuePtr, resultHeader);
while(!isQueueEmpty(tempQueuePtr)){
tempParent=dequeue(tempQueuePtr);
// 左节点
i++;
ch = paraString[i];
if(ch=='#'){
tempParent->left=NULL;
} else{
tempLeftChild=constructBTNode(ch);
enqueue(tempQueuePtr,tempLeftChild);
tempParent->left=tempLeftChild;
}
// 右节点
i++;
ch = paraString[i];
if(ch=='#'){
tempParent->right=NULL;
} else{
tempRightChild=constructBTNode(ch);
enqueue(tempQueuePtr,tempRightChild);
tempParent->right=tempRightChild;
}
}
return resultHeader;
}
四种二叉树遍历

/*
* 按层级输出二叉树数据
*/
void levelwise(BTNodePtr paraTreePtr){
// 用队列管理地址
char tempString[100];
int i=0;
QueuePtr tempQueuePtr=initQueue();
BTNodePtr tempNodePtr;
enqueue(tempQueuePtr, paraTreePtr);
while(!isQueueEmpty(tempQueuePtr)){
tempNodePtr=dequeue(tempQueuePtr);
tempString[i]=tempNodePtr->element;
i++;
if(tempNodePtr->left!=NULL){
enqueue(tempQueuePtr,tempNodePtr->left);
}
if(tempNodePtr->right!=NULL){
enqueue(tempQueuePtr,tempNodePtr->right);
}
}
tempString[i]='\0';
printf("Levelwise: %s\r\n",tempString);
}
/*
* 先序遍历
*/
void preorder(BTNodePtr tempPtr){
if(tempPtr==NULL){
return;
}
printf("%c",tempPtr->element);
preorder(tempPtr->left);
preorder(tempPtr->right);
}
/*
* 中序遍历
*/
void inorder(BTNodePtr tempPtr){
if(tempPtr==NULL){
return;
}
preorder(tempPtr->left);
printf("%c",tempPtr->element);
preorder(tempPtr->right);
}
/*
* 后序遍历
*/
void postorder(BTNodePtr tempPtr){
if(tempPtr==NULL){
return;
}
preorder(tempPtr->left);
preorder(tempPtr->right);
printf("%c",tempPtr->element);
}
程序入口
/*
* 程序入口
*/
int main(){
BTNodePtr tempHeader;
tempHeader=constructBTNode('c');
printf("There is only one node. Preorder visit: ");
preorder(tempHeader);
printf("\r\n");
char* tempString="acde#bf######";
tempHeader=stringToBTree(tempString);
printf("Preorder: ");
preorder(tempHeader);
printf("\r\n");
printf("Inorder: ");
preorder(tempHeader);
printf("\r\n");
printf("Postorder: ");
preorder(tempHeader);
printf("\r\n");
printf("Levelwise: ");
levelwise(tempHeader);
printf("\r\n");
return 0;
}
输出结果
There is only one node. Preorder visit: c
front = 0, rear = 1.
enqueue a ends.
dequeue a ends.
front = 1, rear = 2.
enqueue c ends.
front = 1, rear = 3.
enqueue d ends.
dequeue c ends.
front = 2, rear = 4.
enqueue e ends.
dequeue d ends.
front = 3, rear = 0.
enqueue b ends.
front = 3, rear = 1.
enqueue f ends.
dequeue e ends.
dequeue b ends.
dequeue f ends.
Preorder: acedbf
Inorder: ceadbf
Postorder: cedbfa
Levelwise: front = 0, rear = 1.
enqueue a ends.
dequeue a ends.
front = 1, rear = 2.
enqueue c ends.
front = 1, rear = 3.
enqueue d ends.
dequeue c ends.
front = 2, rear = 4.
enqueue e ends.
dequeue d ends.
front = 3, rear = 0.
enqueue b ends.
front = 3, rear = 1.
enqueue f ends.
dequeue e ends.
dequeue b ends.
dequeue f ends.
Levelwise: acdebf
--------------------------------
Process exited after 0.0106 seconds with return value 0
请按任意键继续. . .
完整代码
#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>
#define QUEUE_SIZE 5
/*
* 二叉树节点
*/
typedef struct BTNode{
char element;
struct BTNode* left;
struct BTNode* right;
}BTNode, *BTNodePtr;
/*
* 存储地址的队列
*/
typedef struct BTNodePtrQueue{
BTNodePtr* nodePtrs;
int front;
int rear;
}BTNodePtrQueue, *QueuePtr;
/*
* 初始化队列
*/
QueuePtr initQueue(){
QueuePtr resultQueuePtr=(QueuePtr)malloc(sizeof(struct BTNodePtrQueue));
resultQueuePtr->nodePtrs=(BTNodePtr*)malloc(QUEUE_SIZE*sizeof(BTNodePtr));
resultQueuePtr->front=0;
resultQueuePtr->rear=1;
return resultQueuePtr;
}
/*
* 判断队列是否为空
*/
bool isQueueEmpty(QueuePtr paraQueuePtr){
if((paraQueuePtr->front+1)%QUEUE_SIZE==paraQueuePtr->rear){
return true;
}
return false;
}
/*
* 将一个元素加入队列
*/
void enqueue(QueuePtr paraQueuePtr, BTNodePtr paraBTNodePtr){
printf("front = %d, rear = %d.\r\n",paraQueuePtr->front, paraQueuePtr->rear);
if((paraQueuePtr->rear+1)%QUEUE_SIZE==paraQueuePtr->front%QUEUE_SIZE){
printf("Error, trying to enqueue %c. queue full.\r\n",paraBTNodePtr->element);
return;
}
paraQueuePtr->nodePtrs[paraQueuePtr->rear]=paraBTNodePtr;
paraQueuePtr->rear=(paraQueuePtr->rear+1)%QUEUE_SIZE;
printf("enqueue %c ends.\r\n",paraBTNodePtr->element);
}
/*
* 从队列中删除一个元素
*/
BTNodePtr dequeue(QueuePtr paraQueuePtr){
if(isQueueEmpty(paraQueuePtr)){
printf("Error, empty queue.\r\n");
return NULL;
}
paraQueuePtr->front=(paraQueuePtr->front+1)%QUEUE_SIZE;
printf("dequeue %c ends.\r\n",paraQueuePtr->nodePtrs[paraQueuePtr->front]->element);
return paraQueuePtr->nodePtrs[paraQueuePtr->front];
}
/*
* 用给定的字符创建一个BTNode的节点
*/
BTNodePtr constructBTNode(char paraChar){
BTNodePtr resultPtr=(BTNodePtr)malloc(sizeof(BTNode));
resultPtr->element=paraChar;
resultPtr->left=NULL;
resultPtr->right=NULL;
return resultPtr;
}
/*
* 用给定的字符串创建一个二叉树
*/
BTNodePtr stringToBTree(char* paraString){
int i=0;
char ch;
// 用队列来管理指针
QueuePtr tempQueuePtr=initQueue();
BTNodePtr resultHeader;
BTNodePtr tempParent, tempLeftChild, tempRightChild;
ch=paraString[i];
resultHeader=constructBTNode(ch);
enqueue(tempQueuePtr, resultHeader);
while(!isQueueEmpty(tempQueuePtr)){
tempParent=dequeue(tempQueuePtr);
// 左节点
i++;
ch = paraString[i];
if(ch=='#'){
tempParent->left=NULL;
} else{
tempLeftChild=constructBTNode(ch);
enqueue(tempQueuePtr,tempLeftChild);
tempParent->left=tempLeftChild;
}
// 右节点
i++;
ch = paraString[i];
if(ch=='#'){
tempParent->right=NULL;
} else{
tempRightChild=constructBTNode(ch);
enqueue(tempQueuePtr,tempRightChild);
tempParent->right=tempRightChild;
}
}
return resultHeader;
}
/*
* 按层级输出二叉树数据
*/
void levelwise(BTNodePtr paraTreePtr){
// 用队列管理地址
char tempString[100];
int i=0;
QueuePtr tempQueuePtr=initQueue();
BTNodePtr tempNodePtr;
enqueue(tempQueuePtr, paraTreePtr);
while(!isQueueEmpty(tempQueuePtr)){
tempNodePtr=dequeue(tempQueuePtr);
tempString[i]=tempNodePtr->element;
i++;
if(tempNodePtr->left!=NULL){
enqueue(tempQueuePtr,tempNodePtr->left);
}
if(tempNodePtr->right!=NULL){
enqueue(tempQueuePtr,tempNodePtr->right);
}
}
tempString[i]='\0';
printf("Levelwise: %s\r\n",tempString);
}
/*
* 先序遍历
*/
void preorder(BTNodePtr tempPtr){
if(tempPtr==NULL){
return;
}
printf("%c",tempPtr->element);
preorder(tempPtr->left);
preorder(tempPtr->right);
}
/*
* 中序遍历
*/
void inorder(BTNodePtr tempPtr){
if(tempPtr==NULL){
return;
}
preorder(tempPtr->left);
printf("%c",tempPtr->element);
preorder(tempPtr->right);
}
/*
* 后序遍历
*/
void postorder(BTNodePtr tempPtr){
if(tempPtr==NULL){
return;
}
preorder(tempPtr->left);
preorder(tempPtr->right);
printf("%c",tempPtr->element);
}
/*
* 程序入口
*/
int main(){
BTNodePtr tempHeader;
tempHeader=constructBTNode('c');
printf("There is only one node. Preorder visit: ");
preorder(tempHeader);
printf("\r\n");
char* tempString="acde#bf######";
tempHeader=stringToBTree(tempString);
printf("Preorder: ");
preorder(tempHeader);
printf("\r\n");
printf("Inorder: ");
inorder(tempHeader);
printf("\r\n");
printf("Postorder: ");
postorder(tempHeader);
printf("\r\n");
printf("Levelwise: ");
levelwise(tempHeader);
printf("\r\n");
return 0;
}
本文介绍了二叉树的基本概念,包括其定义、特点以及在实际问题中的重要性。通过C语言实现了二叉树节点的结构体,以及队列数据结构用于辅助层次遍历。此外,还提供了创建二叉树、四种遍历(先序、中序、后序、层次)的方法,并给出了具体的代码实现。在示例中,展示了如何使用字符串创建二叉树并进行遍历操作。
559

被折叠的 条评论
为什么被折叠?



