一、二叉树的层次遍历
假设二叉树有如下定义:
typedef struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
} TreeNode;
需要一个辅助队列,以下是辅助队列的定义。
//辅助队列结点定义
typedef struct Node {
TreeNode *treeNode;
struct Node *next;
} Node;
typedef struct Queue {
Node *queueHead;
Node *queueTail;
} Queue;
/****** 队列操作 begin ******/
Node *getNewQueueNode(TreeNode *treeNode) {
Node *newNode = (Node *)malloc(sizeof(Node));
if (newNode == NULL) return NULL;
newNode->treeNode = treeNode;
newNode->next = NULL;
return newNode;
}
//初始化一个队列
void initQueue(Queue *q, TreeNode *treeNode) {
Node *newNode = getNewQueueNode(treeNode);
q->queueHead = newNode;
q->queueTail = newNode;
}
//判断队列是否为空
bool queueIsEmpty(Queue q) {
if (q.queueHead == NULL) {
return true;
}
return false;
}
//出队: 保存删除之前的队头元素
void delQueue(Queue *q, TreeNode **delNode) {
Node *tempNode = q->queueHead;
q->queueHead = q->queueHead->next;
*delNode = tempNode->treeNode;
free(tempNode);
}
//入队
void insertQueue(Queue *q, TreeNode *treeNode) {
Node *newNode = getNewQueueNode(treeNode);
q->queueTail->next = newNode;
q->queueTail = newNode;
//避免后续假队空情况
if (q->queueHead == NULL) q->queueHead = newNode;
}
/****** 队列操作 end ******/
二叉树层次遍历的思想:
1、根结点入队
2、若队列非空,则队头结点出队,访问该结点并将其左、右孩子入队(如果孩子结点存在的话)
3、重复3直到队列为空
void levelOrder(TreeNode *rootNode) {
if (rootNode == NULL) return;
Queue q;
initQueue(&q, rootNode);
while (!queueIsEmpty(q)) {
//队头出队
TreeNode *delNode = NULL;
delQueue(&q, &delNode);
printf("%d ", delNode->val);
//孩子入队
if (delNode->left != NULL) {
insertQueue(&q, delNode->left);
}
if (delNode->right != NULL) {
insertQueue(&q, delNode->right);
}
}
}
二、给两棵二叉树的根节点 p和 q ,判断这两棵树是否相同
深度优先遍历 (先序遍历)
1、如果两个二叉树都为空,则两个二叉树相同。
2、如果两个二叉树中有且只有一个为空,则两个二叉树不相同。
3、如果两个二叉树均不为空,判断其根节点的值是否相同,若不相同,则两个二叉树不相同。
4、判断两个二叉树的左子树是否相同以及右子树是否相同。
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
//如果两个树都为空,两者相等
if (p == NULL && q == NULL) return true;
//如果两个树其中一个为空,两者不等
if (p == NULL || q == NULL) return false;
//如果两个树的结点中某个值不一样,两者不等
if (p->val != q->val) return false;
return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}
三、树的中序遍历
递归算法
1、若二叉树为空,则什么也不做
2、若二叉树不为空
(1)中序遍历左子树
(2)访问根节点
(3)中序遍历右子树
void inOrder(TreeNode* rootNode) {
if (rootNode == NULL) return;
inOrder(rootNode->left);
printf("%d ", rootNode->val);
inOrder(rootNode->right);
}
非递归算法
1、沿着根的左孩子,依次入栈,直到左孩子为空
2、栈顶元素出栈并访问:若其有孩子为空,继续执行2;若其右孩子不空,将右子树转执行1
辅助栈设计
typedef struct Node {
TreeNode *treeNode;
struct Node *next;
} Node;
typedef struct Stack {
Node *top;
} Stack;
/****** 栈操作 begin ******/
Node* getNewStackNode(TreeNode* treeNode) {
Node* newNode = (Node *)malloc(sizeof(Node));
if (newNode == NULL) return NULL;
newNode->treeNode = treeNode;
newNode->next = NULL;
return newNode;
}
//初始化
void initStack(Stack* s) {
s->top = NULL;
}
//栈空判断
bool isStackEmpty(Stack s) {
if (s.top == NULL) return true;
return false;
}
//入栈
void pushStack(Stack* s, TreeNode* treeNode) {
Node* newNode = getNewStackNode(treeNode);
newNode->next = s->top;
s->top = newNode;
}
//出栈
void popStack(Stack* s, TreeNode** delNode) {
Node* tempNode = s->top;
s->top = s->top->next;
*delNode = tempNode->treeNode;
free(tempNode);
}
/****** 栈操作 end ******/
算法实现
void inOrder(TreeNode* rootNode) {
if (rootNode == NULL) return;
Stack s;
initStack(&s);
while (rootNode || !isStackEmpty(s)) {
if (rootNode) {
pushStack(&s, rootNode);
rootNode = rootNode->left; //左孩子不空,一路向左
}
else {
TreeNode* delNode = NULL;
popStack(&s, &delNode);
printf("%d ", delNode->val);
rootNode = delNode->right;
}
}
}