写在前面
本文是根据2篇参考文献整合的,后续有关于树的更好的思路会持续更新
树的定义
// lombok 标签 @Data
@Data
public class TreeNode<T>
{
public T Data;
public TreeNode<T> LChild;
public TreeNode<T> RChild;
}
前序遍历
前序递归
public static void PreOrderRecur(TreeNode<char> treeNode)
{
if (treeNode == null)
{
return;
}
Console.Write(treeNode.Data);
PreOrderRecur(treeNode.LChild);
PreOrderRecur(treeNode.RChild);
}
前序非递归
public static void PreOrder(TreeNode<char> head)
{
if (head == null)
{
return;
}
Stack<TreeNode<char>> stack = new Stack<TreeNode<char>>();
stack.Push(head);
while (!(stack.Count == 0))
{
TreeNode<char> cur = stack.Pop();
Console.Write(cur.Data);
if (cur.RChild != null)
{
stack.Push(cur.RChild);
}
if (cur.LChild != null)
{
stack.Push(cur.LChild);
}
}
}
中序遍历
中序递归
public static void InOrderRecur(TreeNode<char> treeNode)
{
if (treeNode == null)
{
return;
}
InOrderRecur(treeNode.LChild);
Console.Write(treeNode.Data);
InOrderRecur(treeNode.RChild);
}
中序非递归
public static void InOrder(TreeNode<char> treeNode)
{
if (treeNode == null)
{
return;
}
Stack<TreeNode<char>> stack = new Stack<TreeNode<char>>();
TreeNode<char> cur = treeNode;
while (!(stack.Count == 0) || cur != null)
{
while (cur != null)
{
stack.Push(cur);
cur = cur.LChild;
}
TreeNode<char> node = stack.Pop();
Console.WriteLine(node.Data);
cur = node.RChild;
}
}
后序遍历
后序递归
public static void PosOrderRecur(TreeNode<char> treeNode)
{
if (treeNode == null)
{
return;
}
PosOrderRecur(treeNode.LChild);
PosOrderRecur(treeNode.RChild);
Console.Write(treeNode.Data);
}
后序非递归
双栈法
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new LinkedList<>();
if (root == null) return result;
Stack<TreeNode> toVisit = new Stack<>();
Stack<TreeNode> reversedStack = new Stack<>();
toVisit.push(root);
TreeNode cur;
while (!toVisit.isEmpty()) {
cur = toVisit.pop();
reversedStack.push(cur); // result.add(cur.val);
if (cur.left != null) toVisit.push(cur.left); // 左节点入栈
if (cur.right != null) toVisit.push(cur.right); // 右节点入栈
}
while (!reversedStack.isEmpty()) {
cur = reversedStack.pop();
result.add(cur.val);
}
return result;
}
}
单Stack
申请一个栈stack,将头节点压入stack,同时设置两个变量 h 和 c,在整个流程中,h代表最近一次弹出并打印的节点,c代表当前stack的栈顶节点,初始时令h为头节点,,c为null;
每次令c等于当前stack的栈顶节点,但是不从stack中弹出节点,此时分一下三种情况:
(1)如果c的左孩子不为空,并且h不等于c的左孩子,也不等于c的右孩子,则吧c的左孩子压入stack中
(2)如果情况1不成立,并且c的右孩子不为空,并且h不等于c的右孩子,则把c的右孩子压入stack中;
(3)如果情况1和2不成立,则从stack中弹出c并打印,然后令h等于c;
一直重复步骤2,直到stack为空.
public static void PosOrderTwo(TreeNode<char> treeNode)
{
if (treeNode == null)
{
return;
}
Stack<TreeNode<char>> stack = new Stack<TreeNode<char>>();
stack.Push(treeNode);
TreeNode<char> h = treeNode;
TreeNode<char> c = null;
while (!(stack.Count == 0))
{
c = stack.Peek();
//c结点有左孩子 并且 左孩子没被遍历(输出)过 并且 右孩子没被遍历过
if (c.LChild != null && h != c.LChild && h != c.RChild)
stack.Push(c.LChild);
//c结点有右孩子 并且 右孩子没被遍历(输出)过
else if (c.RChild != null && h != c.RChild)
stack.Push(c.RChild);
//c结点没有孩子结点 或者孩子结点已经被遍历(输出)过
else
{
TreeNode<char> node = stack.Pop();
Console.WriteLine(node.Data);
h = c;
}
}
}
层次遍历
public static void LevelOrder(TreeNode<char> treeNode)
{
if(treeNode == null)
{
return;
}
Queue<TreeNode<char>> queue = new Queue<TreeNode<char>>();
queue.Enqueue(treeNode);
while (queue.Any())
{
TreeNode<char> node = queue.Dequeue();
Console.Write(node.Data);
if (node.Left != null)
{
queue.Enqueue(node.Left);
}
if (node.Right != null)
{
queue.Enqueue(node.Right);
}
}
}
网友评论