给定一个二叉树,返回它的 前序 遍历。

示例:

输入: [1,null,2,3]
1
\
2
/
3 输出: [1,2,3]

进阶: 递归算法很简单,你可以通过迭代算法完成吗?

前序遍历


前序遍历首先访问根节点,然后遍历左子树,最后遍历右子树。

用c语言来实现比较麻烦,现在大概介绍下我的思路,首先题目先要实现一个前序遍历,如果用递归,会比较简单,几行代码就可以实现,但是现在要求使用迭代发来实现。整个遍历过程是,访问根节点,然后遍历其左子树,然后再看左子树是否有其左孩子和右孩子。因为在查看左孩子之后,还要再查看根节点的右孩子,所以每次需要把根节点记录下来,需要存在栈中。所以我们需要实现一个栈,有压栈和出栈操作。另外我们需要一个链表来存放已经访问过的节点,到最后,需要把这些节点统一存储到一个数组中,然后返回。

下面来看下我码的代码

/* 链表节点 用于存储输出结果 */
struct listNode {
int val;
struct listNode *next;
}; struct list {
int count;
struct listNode *head;
struct listNode *tail;
}; /* 栈节点,用于存储已经遍历过的根节点 */
struct StackNode
{
void *entry;
struct StackNode *next;
}; struct stack {
struct StackNode *top;
}; void init_stack(struct stack *s)
{
s->top = NULL;
} void stack_push(struct stack *s, void *np)
{
struct StackNode *node = malloc(sizeof(struct StackNode));
node->entry = np;
node->next = s->top;
s->top = node;
}; void *stack_pop(struct stack *s)
{
struct StackNode *np = s->top;
void *node = np->entry;
s->top = np->next;
free(np);
return node;
}; bool isEmpty(struct stack *s)
{
return (s->top == NULL) ? true : false;
} void init_list(struct list *l)
{
l->count = 0;
l->head = NULL;
l->tail = NULL;
} void add_new_node(struct list *l, struct listNode *node)
{
if (!l->head)
{
l->head = node;
l->tail = node;
l->count = 1;
return;
} l->tail->next = node;
l->tail = node;
l->count++;
}

这些是辅助函数

int* preorderTraversal(struct TreeNode* root, int* returnSize){
struct TreeNode *pNode = root;
struct listNode *newNode = NULL;
struct list *l = malloc(sizeof(struct list));
struct stack *s = malloc(sizeof(struct stack));
int *r = NULL;
int i = 0;
struct listNode *head = NULL;
init_list(l);
init_stack(s); while (pNode != NULL || !isEmpty(s))
{
if (pNode != NULL)
{
newNode = malloc(sizeof(struct listNode));
newNode->val = pNode->val;
newNode->next = NULL;
add_new_node(l, newNode);
stack_push(s, (void *)pNode);
pNode = pNode->left;
}
else
{
pNode = (struct TreeNode *)stack_pop(s);
pNode = pNode->right;
}
} r = malloc(sizeof(int) * l->count);
head = l->head;
while(head && i < l->count)
{
r[i] = head->val;
i++;
head = head->next;
}
*returnSize = l->count; return r;
}

这个是具体的前序遍历函数。

对应的中序遍历的核心代码如下:

 while (pNode != NULL || !isEmpty(s))
{
if (pNode != NULL)
{
stack_push(s, (void *)pNode);
pNode = pNode->left;
}
else
{
pNode = (struct TreeNode *)stack_pop(s);
newNode = malloc(sizeof(struct listNode));
newNode->val = pNode->val;
newNode->next = NULL;
add_new_node(l, newNode);
pNode = pNode->right;
}
}

后序遍历如下:

while (pNode != NULL || !isEmpty(s))
{
if (pNode != NULL)
{
stack_push(s, (void *)pNode);
pNode = pNode->left;
}
else
{
seek = (struct TreeNode *)stack_seek(s);
if (seek->right == NULL || last == seek->right)
{
stack_pop(s);
newNode = malloc(sizeof(struct listNode));
newNode->val = seek->val;
newNode->next = NULL;
add_new_node(l, newNode);
last = seek;
}
else
{
pNode = seek->right;
}
}
}

(leetcode)二叉树的前序遍历-c语言实现的更多相关文章

  1. (leetcode)二叉树的层次遍历-c语言实现

    这段代码,在后面跑测试用例时,出现了stack-overflow,但是原因还不清楚. 问题如下:  二叉树的层次遍历   给定一个二叉树,返回其按层次遍历的节点值. (即逐层地,从左到右访问所有节点) ...

  2. 【LeetCode题解】144_二叉树的前序遍历

    目录 [LeetCode题解]144_二叉树的前序遍历 描述 方法一:递归 Java 代码 Python 代码 方法二:非递归(使用栈) Java 代码 Python 代码 [LeetCode题解]1 ...

  3. LeetCode:二叉树的前序遍历【144】

    LeetCode:二叉树的前序遍历[144] 题目描述 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 题目分析 如果用递 ...

  4. LeetCode 144. 二叉树的前序遍历(Binary Tree Preorder Traversal)

    144. 二叉树的前序遍历 144. Binary Tree Preorder Traversal 题目描述 给定一个二叉树,返回它的 前序 遍历. LeetCode144. Binary Tree ...

  5. LeetCode:144_Binary Tree Preorder Traversal | 二叉树的前序遍历 | Medium

    题目:Binary Tree Preorder Traversal 二叉树的前序遍历,同样使用栈来解,代码如下: struct TreeNode { int val; TreeNode* left; ...

  6. Java实现 LeetCode 144 二叉树的前序遍历

    144. 二叉树的前序遍历 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] /** * Definition for a ...

  7. Leetcode(144)-二叉树的前序遍历

    给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 二叉树的前序遍历有递归 ...

  8. 【LeetCode】144. 二叉树的前序遍历

    144. 二叉树的前序遍历 知识点:二叉树:递归:Morris遍历 题目描述 给你二叉树的根节点 root ,返回它节点值的 前序 遍历. 示例 输入:root = [1,null,2,3] 输出:[ ...

  9. 剑指offer面试题:输入某二叉树的前序遍历和中序遍历,输出后序遍历

    二叉树的先序,中序,后序如何遍历,不在此多说了.直接看题目描述吧(题目摘自九度oj剑指offer面试题6): 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结 ...

随机推荐

  1. JIRA 测试循环的创建和使用

    3.测试循环 3.1测试循环的创建      测试人员编写完测试用例,并评审通过后:测试负责人可以计划测试循环. 点击JIRA 选择列表栏中的"测试".点击"计划循环测试 ...

  2. Linux vi 命令 – 文本编辑器

    vi命令是linux系统字符界面下的最常用的文本编辑器. vi编辑器是所有linux的标准编辑器,用于编辑任何ASCⅡ文本,对于编辑源程序尤其有用.iv编辑器功能非常强大,可以对文本进行创建,查找,替 ...

  3. 使用SetTrustedCredmanAccessPrivilege获取已保存的凭据

      windows系统中有一个名为SeTrustedCredmanAccessPrivilege的权限,使拥有该特权的进程可作为受信任的调用者访问凭据管理器.   凭据管理器可以从控制面板 -> ...

  4. MySQL常见的函数

    一.概述 功能:类似于java中的方法 好处:提高重用性和隐藏实现细节 调用:select 函数名(实参列表); 二.单行函数 1.字符函数 concat:连接 substr:截取子串 upper:变 ...

  5. transient关键字有何作用

    使用对象流保存对象时,将对象的全部信息都保存了,但是有些信息是不希望保存,如密码,该如何避免该信息的保存? 使用transient关键字修饰的属性,在保存对象时,该属性并不会被保存. transien ...

  6. OpenGL/ES关于像素渲染

    知道着色器的人都会知道一个东西,那就是着色器分为顶点着色器与片元着色器.在移动端真正渲染到手机屏幕上的无非是一些颜色值,但是一个片元是大于一个像素的,一个片元可能包含多个像素,当然一个片元所包含的像素 ...

  7. 使用ensp模拟器中的防火墙(USG6000V)配置NAT(网页版)

    使用ensp模拟器中的防火墙(USG6000V)配置NAT(网页版)一.NAT介绍NAT(Network Address Translation,网络地址转换):简单来说就是将内部私有地址转换成公网地 ...

  8. IP网络主动测评系统——IT运维人员的好帮手

    一.前 言 随着计算机网络的普及和快速发展,互联网已经融入到人们的衣食住行等方方面 面,如工作.购物.音视频聊天.视频会议.朋友圈.抖音.在线网游.网络电影 电视等.毫不夸张地说,现如今大部分人的绝大 ...

  9. eBPF会成为服务网格的未来吗?

    服务网格现状 服务网格为服务提供了复杂的应用层网络管理,如服务发现.流量路由.弹性(超时/重试/断路).认证/授权.可观察性(日志/度量/追踪)等. 在分布式应用的早期,这些要求是通过直接将所需的逻辑 ...

  10. C++ 派生类函数重载与虚函数继承详解

    目录 一.作用域与名字查找 1.作用域的嵌套 2.在编译时进行名字查找 3.名字冲突与继承 4.通过作用域运算符来使用隐藏的成员 二.同名函数隐藏与虚函数覆盖 1.几种必须区分的情况 2.一个更复杂的 ...