二叉树
树是一种非线性数据结构,由n个结点组成的有层次关系的集合,而二叉树是树的一种,特点是最多只有两个子树。一个二叉树由三部分组成,根结点、左子树、右子树。
二叉树的操作
1.队列及相关操作(辅助实现二叉树)
队列中存放二叉树结点
//定义队列
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("队满,不能入队.\r\n", paraBTNodePtr->element);
return;
}
paraQueuePtr->nodePtrs[paraQueuePtr->rear] = paraBTNodePtr;
paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE;
printf("入队 %c.\r\n", paraBTNodePtr->element);
}
//出队
BTNodePtr dequeue(QueuePtr paraQueuePtr)
{
if(isQueueEmpty(paraQueuePtr))
{
printf("队空,不能出队.\r\n");
return NULL;
}
paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE;
printf("出队 %c.\r\n", paraQueuePtr->nodePtrs[paraQueuePtr->front]->element);
return paraQueuePtr->nodePtrs[paraQueuePtr->front];
}
2.二叉树结点
//二叉树结点
typedef struct BTNode
{
char element;
struct BTNode* left;
struct BTNode* right;
} BTNode, *BTNodePtr;
3.初始化
//初始化二叉树
BTNodePtr constructBTNode(char paraChar)
{
BTNodePtr resultPtr = (BTNodePtr)malloc(sizeof(BTNode));
resultPtr->element = paraChar;
resultPtr->left = NULL;
resultPtr->right = NULL;
return resultPtr;
}
4.创建二叉树
//创建二叉树
BTNodePtr stringToBTree(char* paraString)
{
int i;
char ch;
//运用队列进行创建
QueuePtr tempQueuePtr = initQueue();
BTNodePtr resultHeader;
BTNodePtr tempParent, tempLeftChild, tempRightChild;
i = 0;
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;
}
图解
5.遍历(递归)
1.前序遍历
根左右,示例遍历结果: abdfhce
//前序遍历
void preorder(BTNodePtr tempPtr)
{
if (tempPtr == NULL)
{
return;
}
printf("%c", tempPtr->element);
preorder(tempPtr->left);
preorder(tempPtr->right);
}
2.中序遍历
左根右,示例遍历结果: dfbhace
//中序遍历
void inorder(BTNodePtr tempPtr)
{
if(tempPtr == NULL)
{
return;
}
inorder(tempPtr->left);
printf("%c", tempPtr->element);
inorder(tempPtr->right);
}
3.后序遍历
左右根,示例遍历结果:fdhbeca
//后序遍历
void postorder(BTNodePtr tempPtr)
{
if (tempPtr == NULL) {
return;
}//Of if
postorder(tempPtr->left);
postorder(tempPtr->right);
printf("%c", tempPtr->element);
}
4.层序遍历
示例遍历结果:abcdhef
//层序遍历
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("层序遍历: %s\r\n", tempString);
}
总代码
#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)
{
printf("队满,不能入队.\r\n", paraBTNodePtr->element);
return;
}
paraQueuePtr->nodePtrs[paraQueuePtr->rear] = paraBTNodePtr;
paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE ;
printf("入队 %c.\r\n", paraBTNodePtr->element);
}
//出队
BTNodePtr dequeue(QueuePtr paraQueuePtr)
{
if(isQueueEmpty(paraQueuePtr))
{
printf("队空,不能出队.\r\n");
return NULL;
}
paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE ;
printf("出队 %c.\r\n", paraQueuePtr->nodePtrs[paraQueuePtr->front]->element);
return paraQueuePtr->nodePtrs[paraQueuePtr->front];
}
//初始化二叉树
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;
char ch;
//运用队列进行创建
QueuePtr tempQueuePtr = initQueue();
BTNodePtr resultHeader;
BTNodePtr tempParent, tempLeftChild, tempRightChild;
i = 0;
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("层序遍历: %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;
}
inorder(tempPtr->left);
printf("%c", tempPtr->element);
inorder(tempPtr->right);
}
//后序遍历
void postorder(BTNodePtr tempPtr)
{
if (tempPtr == NULL) {
return;
}//Of if
postorder(tempPtr->left);
postorder(tempPtr->right);
printf("%c", tempPtr->element);
}
int main()
{
BTNodePtr tempHeader;
tempHeader = constructBTNode('c');
printf("只有一个结点时. 先序遍历: ");
preorder(tempHeader);
printf("\r\n");
char* tempString = "abcdh#e#f######";
tempHeader = stringToBTree(tempString);
printf("前序遍历: ");
preorder(tempHeader);
printf("\r\n");
printf("中序遍历: ");
inorder(tempHeader);
printf("\r\n");
printf("后序遍历: ");
postorder(tempHeader);
printf("\r\n");
printf("层序遍历: ");
levelwise(tempHeader);
printf("\r\n");
return 1;
}
运行结果
只有一个结点时. 先序遍历: c
front = 0, rear = 1.
入队 a.
出队 a.
front = 1, rear = 2.
入队 b.
front = 1, rear = 3.
入队 c.
出队 b.
front = 2, rear = 4.
入队 d.
front = 2, rear = 0.
入队 h.
出队 c.
front = 3, rear = 1.
入队 e.
出队 d.
front = 4, rear = 2.
入队 f.
出队 h.
出队 e.
出队 f.
前序遍历: abdfhce
中序遍历: dfbhace
后序遍历: fdhbeca
层序遍历: front = 0, rear = 1.
入队 a.
出队 a.
front = 1, rear = 2.
入队 b.
front = 1, rear = 3.
入队 c.
出队 b.
front = 2, rear = 4.
入队 d.
front = 2, rear = 0.
入队 h.
出队 c.
front = 3, rear = 1.
入队 e.
出队 d.
front = 4, rear = 2.
入队 f.
出队 h.
出队 e.
出队 f.
层序遍历: abcdhef