数据结构——Tree

一、二叉树的层次遍历

假设二叉树有如下定义:

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;
		}
	}
}

  • 8
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值