一、二叉树理论基础
1 理解满二叉树,完全二叉树,平衡二叉树和二叉搜索树的概念;
2 二叉树存储方式:其一是数组线性存储;其二是链表链式存储;
3 二叉树遍历方式:1)前序遍历;2)中序遍历;3)后序遍历;
4 二叉树定义:
struct TreeNode
{
int* val;
struct TreeNode* left;
struct TreeNode* right;
}
5 二叉树的遍历方法:1) 递归方法;2)迭代方法;
1)递归
a.递归函数的参数和返回值;
b.确定终止条件
c.确定单层递归逻辑
leetcode题目:
144. 前序遍历:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
void traversal(struct TreeNode* cur, int* result, int* index)
{
/**前序遍历 中-左-右**/
if(cur == NULL) return;
result[(*index)++] = cur->val;
traversal(cur->left, result, index);
traversal(cur->right, result, index);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
struct TreeNode* cur = root;
*returnSize = 0;
traversal(cur, result, returnSize);
return result;
}
94. 中序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
void traversal(struct TreeNode* cur, int* result, int* index)
{
/**中序遍历 左-中-右**/
if(cur == NULL) return;
traversal(cur->left, result, index);
result[(*index)++] = cur->val;
traversal(cur->right, result, index);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
struct TreeNode* cur = root;
*returnSize = 0;
traversal(cur, result, returnSize);
return result;
}
145.后序遍历
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
void traversal(struct TreeNode* cur, int* result, int* index)
{
/**后序遍历 左-右-中**/
if(cur == NULL) return;
traversal(cur->left, result, index);
traversal(cur->right, result, index);
result[(*index)++] = cur->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize) {
int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
struct TreeNode* cur = root;
*returnSize = 0;
traversal(cur, result, returnSize);
return result;
}
2)迭代
前序和后序遍历可以统一成为一个code风格,前序调整顺序再翻转数组就是后序。
注意点:a. 用数组来保存节点(指针);b. cur指针的位置变化
/**迭代法**/
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = 0;
if(root == NULL)
return NULL;
int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
struct TreeNode** stk = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 110);//用来做栈
int stk_idx = 0;
struct TreeNode* cur = root;
//traversal(cur, result, returnSize);
/**前序遍历 先把中间节点数值压入栈内**/
stk[stk_idx++] = root;
while(stk_idx > 0)
{
/**节点值放入result**/
result[(*returnSize)++] = (stk[--stk_idx])->val;//stk_indx填了数字 位置加了1
cur = stk[stk_idx];
/**压入右节点, 后压入左节点**/
if(cur->right)
{
stk[stk_idx++] = cur->right;
}
if(cur->left)
{
stk[stk_idx++] = cur->left;
}
}
return result;
}
//另外提供一种写法,和栈契合度高些
/** 栈的思想
前序遍历:中左右
头节点先入栈;
当栈不为空,一直执行下面操作:
1-从栈中pop元素作为当前节点,写入数组中;
2-因为栈是先入后出,所以先把右边的节点入栈,再入左边的,这样出栈时候就先左后右
3-直到栈元素为空
**/
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
/**用数组模拟栈**/
int stk_base = -1;//栈底位置
*returnSize = 0;
struct TreeNode** NodeList = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 101);
NodeList[++stk_base] = root;
int* result = (int*)malloc(sizeof(int) * 101);
if(root == NULL)
{
return NULL;
}
/**栈不为空时候**/
while(stk_base > -1)
{
//pop出栈
struct TreeNode* curNode = NodeList[stk_base];
result[(*returnSize)++] = curNode->val;
stk_base--;//相当于出栈
//把右节点 左节点入栈
if(curNode->right)
NodeList[++stk_base] = curNode->right;
if(curNode->left)
NodeList[++stk_base] = curNode->left;
}
return result;
}
/**迭代法**/
void reserve(int* arr, int size)
{
int left = 0;
int right = size -1;
while(left < right)
{
int tmp = arr[right];
arr[right] = arr[left];
arr[left] = tmp;
left++;
right--;
}
}
int* postorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = 0;
if(root == NULL)
return NULL;
int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
struct TreeNode** stk = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 110);//用来做栈
int stk_idx = 0;
struct TreeNode* cur = root;
//traversal(cur, result, returnSize);
/**前序遍历 先把中间节点数值压入栈内**/
stk[stk_idx++] = root;
while(stk_idx > 0)
{
/**节点值放入result**/
result[(*returnSize)++] = (stk[--stk_idx])->val;//stk_indx填了数字 位置加了1
cur = stk[stk_idx];
/**压入左节点, 后压入右节点**/
if(cur->left)
{
stk[stk_idx++] = cur->left;
}
if(cur->right)
{
stk[stk_idx++] = cur->right;
}
}
reserve(result, *returnSize);
return result;
}
中序遍历:
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = 0;
if(root == NULL)
return NULL;
int* result = (int*)malloc(sizeof(int) * 110);//最大数目是100
struct TreeNode** stk = (struct TreeNode**)malloc(sizeof(struct TreeNode*) * 110);//用来做栈
int stk_idx = 0;
struct TreeNode* cur = root;
//traversal(cur, result, returnSize);
while(stk_idx > 0 || cur)
{
/**如果cur不为空,一直往左子树遍历,加入栈中**/
if(cur)
{
stk[stk_idx++] = cur;
cur = cur->left;
}
else
{
//保存中间数值
result[(*returnSize)++] = (stk[--stk_idx])->val;
cur = stk[stk_idx];//当前是栈弹出的node
//save right node
cur = cur->right;
}
}
return result;
}
此外,代码随想录提供思路,把迭代法统一风格,就是在入栈时候,加入节点同时,也加入一个空节点进行标记。