目录
1)定义、理解:
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、被分别称为左子树和右子树的二叉树组成,是有序树。(如图)
代码实现:
用结构体建立节点,然后用指针链接节点,每个节点内有俩个指针,这样就可以如图上一样链接了。
typedef struct BTNode {
char element;
BTNode* left;
BTNode* right;
}BTNode, *BTNodePtr;
2)初始化(逐层赋值)
初始化代码:
代码将会一层一层给二叉树赋值(如图)
赋值代码实现:
因为是一层一层的从左到右的,所以当我们给其中一层赋值完了后需要记录这一层的节点以便访问下一层-----就像图中第二部给B节点赋值完后需要记录B节点,再给C赋值并记录C节点,然后通过B节点先访问B的左子节点然后右子节点(都要记录,除非子节点是空的),然后再是通过C节点往下访问。显然这样的过程是一个先记录(存储),先访问的过程;队列便会出现在我们的脑中所以代码实现:
首先定义一个栈来存储节点指针:
typedef struct BTNodePtrQueue{
BTNodePtr* nodePtrs;
int front;
int rear;
}BTNodePtrQueue, *QueuePtr;
给它初始化:
QueuePtr initQueue() {
QueuePtr resultQueuePtr = (QueuePtr)malloc(sizeof(BTNodePtrQueue));
resultQueuePtr->nodePtrs = (BTNodePtr*)malloc(QUEUE_SIZE * sizeof(BTNodePtr));
resultQueuePtr->front = 0;
resultQueuePtr->rear = 1;
return resultQueuePtr;
}
进队和出对代码:
void enqueue(QueuePtr paraQueuePtr, BTNodePtr paraBTNodePtr) {
//判断队是否满了,队满了是什么意思呢?
if((paraQueuePtr->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) {
printf("Error, tring to enqueue %c. queue full.\n", paraBTNodePtr->element);
return;
}
//插入
paraQueuePtr->nodePtrs[paraQueuePtr->rear] = paraBTNodePtr;
paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE;
//paraQueuePtr->rear++;
printf("enqueue %c ends.\n", paraBTNodePtr->element);
}
BTNodePtr dequeue(QueuePtr paraQueuePtr) {
if (isQueueEmpty(paraQueuePtr)) {
printf("Error, empty queue\n");
return NULL;
}
paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE;
//BTNodePTr tempPtr = paraQueuePtr->nodePtrs[paraQueuePtr->front + 1];
printf("dequeue %c ends.\n", paraQueuePtr->nodePtrs[paraQueuePtr->front]->element);
return paraQueuePtr->nodePtrs[paraQueuePtr->front];
}
然后就是将有序字符串存入二叉树:
BTNodePtr stringToBTtree(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;
}
3)四种便利
1.逐层便利
和逐层赋值一样前者为输入、后者为输出:
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("LeveWise: %s\r\n", tempString);
}
2.前序遍历
‘前’的意思是先访问父节点再访问子节点。
图片:
递归代码
void preorder(BTNodePtr tempPtr) {
if (tempPtr == NULL) {
return;
}
printf("%c", tempPtr->element);
preorder(tempPtr->left);
preorder(tempPtr->right);
}
3.中序遍历
‘中’的意思是先访问左子节点再访问父节点最后是右子节点。
图片:
递归代码
void inorder(BTNodePtr paraPtr){
if (paraPtr == NULL) {
return;
}
inorder(paraPtr->left);
printf("%c", paraPtr->element);
inorder(paraPtr->right);
}
4.后序遍历
‘后’的意思是先左子节点然后右节点最后父节点。
图片:
递归代码
void postorder(BTNodePtr paraPtr) {
if (paraPtr == NULL) {
return;
}
postorder(paraPtr->left);
postorder(paraPtr->right);
printf("%c", paraPtr->element);
}
总代码:
#include <stdio.h>
#include <malloc.h>
#define QUEUE_SIZE 5
/**
* Binary tree node.
*/
typedef struct BTNode {
char element;
BTNode* left;
BTNode* right;
}BTNode, *BTNodePtr;
/**
* A queue with a number of pointers.
*/
typedef struct BTNodePtrQueue{
BTNodePtr* nodePtrs;
int front;
int rear;
}BTNodePtrQueue, *QueuePtr;
/**
* Initialize the queue.
*/
QueuePtr initQueue() {
QueuePtr resultQueuePtr = (QueuePtr)malloc(sizeof(BTNodePtrQueue));
resultQueuePtr->nodePtrs = (BTNodePtr*)malloc(QUEUE_SIZE * sizeof(BTNodePtr));
resultQueuePtr->front = 0;
resultQueuePtr->rear = 1;
return resultQueuePtr;
} //Of initQueue.
/**
* Is the queue empty?
*/
//判断的是队是否为空而不是树
int isQueueEmpty(QueuePtr paraQueuePtr) {
if ((paraQueuePtr->front + 1) % QUEUE_SIZE ==paraQueuePtr->rear) {
return 1;
}
return 0;//非空
}//Of isQueueEmpty.
/**
* Add a pointer to the queue.
*/
void enqueue(QueuePtr paraQueuePtr, BTNodePtr paraBTNodePtr) {
//判断队是否满了,队满了是什么意思呢?
if((paraQueuePtr->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) {
printf("Error, tring to enqueue %c. queue full.\n", paraBTNodePtr->element);
return;
}
//插入
paraQueuePtr->nodePtrs[paraQueuePtr->rear] = paraBTNodePtr;
paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE;
//paraQueuePtr->rear++;
printf("enqueue %c ends.\n", paraBTNodePtr->element);
}//Of enqueue
/**
* Remove an elemnt from the queue and return.
*/
BTNodePtr dequeue(QueuePtr paraQueuePtr) {
if (isQueueEmpty(paraQueuePtr)) {
printf("Error, empty queue\n");
return NULL;
}
paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE;
//BTNodePTr tempPtr = paraQueuePtr->nodePtrs[paraQueuePtr->front + 1];
printf("dequeue %c ends.\n", paraQueuePtr->nodePtrs[paraQueuePtr->front]->element);
return paraQueuePtr->nodePtrs[paraQueuePtr->front];
}//Of dequeue.
/**
* Construct a BTNode using the given char.
*/
BTNodePtr constructBTNode(char paraChar) {
BTNodePtr resultPtr = (BTNodePtr)malloc(sizeof(BTNode));
resultPtr->element = paraChar;
resultPtr->left = NULL;
resultPtr->right = NULL;
return resultPtr;
} //Of constructBTNodePtr
/**
* Construct a binary tree using the given string.
*/
BTNodePtr stringToBTtree(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;
}
/**
* Levelwise.
*/
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("LeveWise: %s\r\n", tempString);
}//Of levewise.
//利用递归完成三种便利。
/**
* Preorder.
*/
void preorder(BTNodePtr tempPtr) {
if (tempPtr == NULL) {
return;
}
printf("%c", tempPtr->element);
preorder(tempPtr->left);
preorder(tempPtr->right);
}//Of preorder
/**
* Inorder.
*/
void inorder(BTNodePtr paraPtr){
if (paraPtr == NULL) {
return;
}
inorder(paraPtr->left);
printf("%c", paraPtr->element);
inorder(paraPtr->right);
}//Of inorder
/**
* Post order.
*/
void postorder(BTNodePtr paraPtr) {
if (paraPtr == NULL) {
return;
}
postorder(paraPtr->left);
postorder(paraPtr->right);
printf("%c", paraPtr->element);
}//Of postorder
/**
* The entrance.
*/
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 = stringToBTtree(tempString);
printf("Preorder: ");
preorder(tempHeader);
printf("\r\n");
printf("Inoder:");
inorder(tempHeader);
printf("\r\n");
printf("Postorder: ");
inorder(tempHeader);
printf("\r\n");
printf("Levelwise: ");
levelwise(tempHeader);
printf("\r\n");
return 0;
}