目录
1 二叉树的形式
2 构造二叉树
2.1 代码实现(誊抄自闵帆老师)
#include <stdio.h>
#include <malloc.h>
#include <stdbool.h>
#define QUEUE_SIZE 5
/**
* Binary tree node.
*/
typedef struct BTNode{
char element;
struct BTNode* left;
struct 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(struct BTNodePtrQueue));
resultQueuePtr->nodePtrs = (BTNodePtr*)malloc(QUEUE_SIZE * sizeof(BTNodePtr));
resultQueuePtr->front = 0;
resultQueuePtr->rear = 1;
return resultQueuePtr;
}//Of initQueue
/**
* Is the queue empty?
*/
bool isQueueEmpty(QueuePtr paraQueuePtr){
if ((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear) {
return true;
}//Of if
return false;
}//Of isQueueEmpty
/**
* Add a pointer to the queue.
*/
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;
}//Of if
paraQueuePtr->nodePtrs[paraQueuePtr->rear] = paraBTNodePtr;
paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE;
printf("enqueue %c ends.\r\n", paraBTNodePtr->element);
}//Of enqueue
/**
* Remove an element from the queue and return.
*/
BTNodePtr dequeue(QueuePtr paraQueuePtr){
if (isQueueEmpty(paraQueuePtr)) {
printf("Error, empty queue\r\n");
return NULL;
}//Of if
paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE;
//BTNodePtr tempPtr = paraQueuePtr->nodePtrs[paraQueuePtr->front + 1];
printf("dequeue %c ends.\r\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 constructBTNode
/**
* Construct a binary tree using the given string.
*/
BTNodePtr stringToBTree(char* paraString){
int i;
char ch;
//Use a queue to manage the pointers
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);
//The left child
i ++;
ch = paraString[i];
if (ch == '#') {
tempParent->left = NULL;
} else {
tempLeftChild = constructBTNode(ch);
enqueue(tempQueuePtr, tempLeftChild);
tempParent->left = tempLeftChild;
}//Of if
//The right child
i ++;
ch = paraString[i];
if (ch == '#') {
tempParent->right = NULL;
} else {
tempRightChild = constructBTNode(ch);
enqueue(tempQueuePtr, tempRightChild);
tempParent->right = tempRightChild;
}//Of if
}//Of while
return resultHeader;
}//Of stringToBTree
/**
* Levelwise.
*/
void levelwise(BTNodePtr paraTreePtr){
//Use a queue to manage the pointers
char tempString[100];
int i = 0;
QueuePtr tempQueuePtr = initQueue();
BTNodePtr tempNodePtr;
enqueue(tempQueuePtr, paraTreePtr);
while(!isQueueEmpty(tempQueuePtr)) {
tempNodePtr = dequeue(tempQueuePtr);
//For output.
tempString[i] = tempNodePtr->element;
i ++;
if (tempNodePtr->left != NULL){
enqueue(tempQueuePtr, tempNodePtr->left);
}//Of if
if (tempNodePtr->right != NULL){
enqueue(tempQueuePtr, tempNodePtr->right);
}//Of if
}//Of while
tempString[i] = '\0';
printf("Levelwise: %s\r\n", tempString);
}//Of levelwise
/**
* Preorder.
*/
void preorder(BTNodePtr tempPtr){
if (tempPtr == NULL){
return;
}//Of if
printf("%c", tempPtr->element);
preorder(tempPtr->left);
preorder(tempPtr->right);
}//Of preorder
/**
* Inorder.
*/
void inorder(BTNodePtr tempPtr){
if (tempPtr == NULL) {
return;
}//Of if
inorder(tempPtr->left);
printf("%c", tempPtr->element);
inorder(tempPtr->right);
}//Of inorder
/**
* Post order.
*/
void postorder(BTNodePtr tempPtr){
if (tempPtr == NULL) {
return;
}//Of if
postorder(tempPtr->left);
postorder(tempPtr->right);
printf("%c", tempPtr->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 = 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 1;
}//Of main
2.2 代码实现效果
3 遍历二叉树的几种方式
3.1递归遍历二叉树
3.1.1 先序递归
1. 访问根结点
2.先序遍历左子树
3.先序遍历右子树
3.1.2 中序递归
1. 中序遍历左子树
2. 访问根结点
3.中序遍历右子树
3.1.3 后序递归
1.后续遍历左子树
2.后续遍历右子树
3.访问根节点
3.2 按照层次遍历二叉树
3.2.1 实现思路
1.我们定义一个队列,先将根结点入队;
2.当前结点是队头结点,将其出队并访问;
3.若当前结点的左结点不为空将左结点入队;若当前结点的右结点不为空将其入队 即可。
3.2.2 图解分析
3.3 代码实现(誊抄自闵帆老师)
#include<iostream>
#include<cstdlib>
#include<stack>
#include<queue>
using namespace std;
typedef struct BinTreeNode
{
char data;
struct BinTreeNode *leftChild;
struct BinTreeNode *rightChild;
}*myTree;
//函数申明
void CreateBinTree(myTree tree);
//二叉树递归遍历
void preorderTraversal(myTree tree); //(中左右)
void inorderTraversal(myTree tree); //(左中右)
void orderTraversal(myTree tree); //(右中左)
//二叉树的栈(非递归)遍历
void PreOrder_NoRecurve1(myTree p); //先序遍历
void InOrder_NoRecurve(myTree p); //中序遍历
void PostOrder_NoRecurve(myTree p); //后序遍历
//二叉树的队列(非递归)遍历
void LevelOrder(myTree p);
int main()
{
cout<<"请输入你要创建的二叉树(以#结束):";
myTree root = NULL;
CreateBinTree(root);
return 0;
}
//使用广义表创建二叉树函数,这里以“字符”创建二叉树,以'#'字符代表结束
void CreateBinTree(myTree root)
{
stack<myTree> s;
int k; //k是处理左、右子树的标记
myTree p,t; //p用来记住当前创建的节点,t用来记住栈顶的元素
char ch;
cin>>ch;
while(ch != '#')
{
switch(ch)
{
case '(': //对(做处理
s.push(p);
k=1;
break;
case ')': //对)做处理
s.pop();
break;
case ',': //对,做处理
k=2;
break;
default:
p = (myTree)malloc(sizeof(BinTreeNode)); //构造一个结点
p->leftChild = NULL;
p->rightChild = NULL;
if (root == NULL) //如果头节点是空
{
root = p;
p->data = ch;
}
else if (k == 1) //链入*t的左孩子
{
t = s.top();
t->leftChild = p;
p->data = ch;
}
else //链入*t的右孩子
{
t = s.top();
t->rightChild = p;
p->data = ch;
}
}
cin>>ch;
}
cout<<endl<<"采用递归遍历二叉树"<<endl;
cout<<"使用中左右输出:";
preorderTraversal(root);
cout<<endl;
cout<<"使用左中右输出:";
inorderTraversal(root);
cout<<endl;
cout<<"使用左右中输出:";
orderTraversal(root);
cout<<endl<<endl<<"采用栈遍历二叉树:"<<endl;
cout<<"使用先序输出:";
PreOrder_NoRecurve1(root);
cout<<endl;
cout<<"使用中序输出: ";
InOrder_NoRecurve(root);
cout<<endl;
cout<<"使用后序输出:";
PostOrder_NoRecurve(root);
cout<<endl;
cout<<endl<<"采用层次遍历(队列)二叉树:" <<endl;
LevelOrder(root);
cout<<endl;
}
/*myTree constructABinaryTree() { //创建一个二叉树
myTree root = (myTree)malloc(sizeof(BinTreeNode));
root->data = 5;
root->leftChild = NULL;
root->leftChild = NULL;
myTree leftChild = (myTree)malloc(sizeof(BinTreeNode));
leftChild->data = 7;
leftChild->leftChild = NULL;
leftChild->rightChild = NULL;
root->leftChild = leftChild;
myTree rightChild = (myTree)malloc(sizeof(BinTreeNode));
rightChild->data = 6;
rightChild->leftChild = NULL;
rightChild->rightChild = NULL;
root->rightChild = rightChild;
myTree twoLeftChild = (myTree)malloc(sizeof(BinTreeNode));
twoLeftChild->data = 4;
twoLeftChild->leftChild = NULL;
twoLeftChild->rightChild = NULL;
leftChild->leftChild = twoLeftChild;
myTree leftRightChild = (myTree)malloc(sizeof(BinTreeNode));
leftRightChild->data = 3;
leftRightChild->leftChild = NULL;
leftRightChild->rightChild = NULL;
leftChild->rightChild = leftRightChild;
return root;
}*/
void preorderTraversal(myTree tree)
{
cout << tree->data << " ";
if (tree->leftChild != NULL) preorderTraversal(tree->leftChild);
if (tree->rightChild != NULL)preorderTraversal(tree->rightChild); //中左右
}
void inorderTraversal(myTree tree)
{
if (tree->leftChild != NULL) inorderTraversal(tree->leftChild); //左中右
cout << tree->data << " ";
if (tree->rightChild != NULL)inorderTraversal(tree->rightChild);
}
void orderTraversal(myTree tree) //左右中、
{
if (tree->leftChild != NULL) orderTraversal(tree->leftChild);
if (tree->rightChild != NULL)orderTraversal(tree->rightChild);
cout << tree->data<<" ";
}
void PreOrder_NoRecurve1(myTree p) //先序遍历
{
stack<myTree> s;
s.push(NULL); /*最先push一个NULL,到最后一个结点没有左右子树时,
栈里只有一个NULL了,令指针p指向这个NULL,再判断就会结束循环*/
while (p!=NULL)
{
cout << p->data << " ";
if(p->rightChild!=NULL) //预留右子树指针在栈中
{
s.push(p->rightChild);
}
if (p->leftChild!=NULL) //进左子树
{
p = p->leftChild;
}
else //左子树为空
{
p = s.top();
s.pop();
}
}
}
void InOrder_NoRecurve(myTree p) //中序遍历
{
stack<myTree> s;
do
{
while (p!=NULL)
{
s.push(p);
p = p->leftChild;
}
if (!s.empty())
{
p = s.top();
s.pop();
cout << p->data << " ";
p = p->rightChild;
}
}
while (p!=NULL||!s.empty());
}
void PostOrder_NoRecurve(myTree p) //后序遍历
{
if (p == NULL)
return ;
stack<myTree> s;
s.push(p);
myTree lastPop = NULL;
while (!s.empty())
{
while (s.top()->leftChild != NULL)
s.push(s.top()->leftChild);
while (!s.empty())
{
//右叶子结点 || 没有右结点
if (lastPop == s.top()->rightChild || s.top()->rightChild == NULL)
{
cout << s.top()->data << " ";
lastPop = s.top();
s.pop();
}
else if (s.top()->rightChild != NULL)
{
s.push(s.top()->rightChild);
break;
}
}
}
}
void LevelOrder(myTree p) //队列层次遍历
{
queue<myTree> Q;
Q.push(p); //根节点进队
myTree t;
while (!Q.empty())
{
t = Q.front(); //t先记住队头,再将队头出队
Q.pop();
cout << t->data << " "; //访问队头元素的数据
if (t->leftChild != NULL)
{
Q.push(t->leftChild);
}
if (t->rightChild != NULL)
{
Q.push(t->rightChild);
}
}
}