数据结构——树的遍历
来源:互联网 发布:linux内核架构 编辑:程序博客网 时间:2024/06/15 16:18
原文地址:Tree Traversals
不像线性数据结构(数组,列表,队列,堆栈等),它们在逻辑上只有一种遍历方式,树可以有不同的遍历方式。下面就是遍历树的一般所用的方法:
Algorithm Inorder(tree) 1. Traverse the left subtree, i.e., call Inorder(left-subtree) 2. Visit the root. 3. Traverse the right subtree, i.e., call Inorder(right-subtree)
中序遍历应用:
在二叉查询树(BST)中,中序遍历是非递减遍历已知节点。可以通过中序遍历的一个变量得到BST的非递减顺序。
例如:上图的中序遍历是:4 2 5 1 3。
先序遍历:
Algorithm Preorder(tree) 1. Visit the root. 2. Traverse the left subtree, i.e., call Preorder(left-subtree) 3. Traverse the right subtree, i.e., call Preorder(right-subtree)
先序遍历的应用:
先序遍历可以用于建立一个树的拷贝。先序遍历也可以用于在表达式树中获取前缀表达式。请看http://en.wikipedia.org/wiki/Polish_notation就知道为啥前缀表达式是有用的了。
例如:上图的先序遍历是:1 2 4 5 3。
后续遍历:
Algorithm Postorder(tree) 1. Traverse the left subtree, i.e., call Postorder(left-subtree) 2. Traverse the right subtree, i.e., call Postorder(right-subtree) 3. Visit the root.
后序遍历的应用:
后续遍历可以用于删除树。请看树的删除问题的详细描述。在一个表达式树中,后序遍历也可以用于获取后缀表达式。请看http://en.wikipedia.org/wiki/Reverse_Polish_notation,后缀表达式的用法。
例如:上图的后序遍历为:4 5 2 3 1。
C语言实现
// C program for different tree traversals#include <stdio.h>#include <stdlib.h>/* A binary tree node has data, pointer to left child and a pointer to right child */struct node{ int data; struct node* left; struct node* right;};/* Helper function that allocates a new node with the given data and NULL left and right pointers. */struct node* newNode(int data){ struct node* node = (struct node*) malloc(sizeof(struct node)); node->data = data; node->left = NULL; node->right = NULL; return(node);}/* Given a binary tree, print its nodes according to the "bottom-up" postorder traversal. */void printPostorder(struct node* node){ if (node == NULL) return; // first recur on left subtree printPostorder(node->left); // then recur on right subtree printPostorder(node->right); // now deal with the node printf("%d ", node->data);}/* Given a binary tree, print its nodes in inorder*/void printInorder(struct node* node){ if (node == NULL) return; /* first recur on left child */ printInorder(node->left); /* then print the data of node */ printf("%d ", node->data); /* now recur on right child */ printInorder(node->right);}/* Given a binary tree, print its nodes in preorder*/void printPreorder(struct node* node){ if (node == NULL) return; /* first print data of node */ printf("%d ", node->data); /* then recur on left sutree */ printPreorder(node->left); /* now recur on right subtree */ printPreorder(node->right);} /* Driver program to test above functions*/int main(){ struct node *root = newNode(1); root->left = newNode(2); root->right = newNode(3); root->left->left = newNode(4); root->left->right = newNode(5); printf("\nPreorder traversal of binary tree is \n"); printPreorder(root); printf("\nInorder traversal of binary tree is \n"); printInorder(root); printf("\nPostorder traversal of binary tree is \n"); printPostorder(root); getchar(); return 0;}
Java语言实现
// Java program for different tree traversals/* Class containing left and right child of current node and key value*/class Node{ int key; Node left, right; public Node(int item) { key = item; left = right = null; }}class BinaryTree{ // Root of Binary Tree Node root; BinaryTree() { root = null; } /* Given a binary tree, print its nodes according to the "bottom-up" postorder traversal. */ void printPostorder(Node node) { if (node == null) return; // first recur on left subtree printPostorder(node.left); // then recur on right subtree printPostorder(node.right); // now deal with the node System.out.print(node.key + " "); } /* Given a binary tree, print its nodes in inorder*/ void printInorder(Node node) { if (node == null) return; /* first recur on left child */ printInorder(node.left); /* then print the data of node */ System.out.print(node.key + " "); /* now recur on right child */ printInorder(node.right); } /* Given a binary tree, print its nodes in preorder*/ void printPreorder(Node node) { if (node == null) return; /* first print data of node */ System.out.print(node.key + " "); /* then recur on left sutree */ printPreorder(node.left); /* now recur on right subtree */ printPreorder(node.right); } // Wrappers over above recursive functions void printPostorder() { printPostorder(root); } void printInorder() { printInorder(root); } void printPreorder() { printPreorder(root); } // Driver method public static void main(String[] args) { BinaryTree tree = new BinaryTree(); tree.root = new Node(1); tree.root.left = new Node(2); tree.root.right = new Node(3); tree.root.left.left = new Node(4); tree.root.left.right = new Node(5); System.out.println("Preorder traversal of binary tree is "); tree.printPreorder(); System.out.println("\nInorder traversal of binary tree is "); tree.printInorder(); System.out.println("\nPostorder traversal of binary tree is "); tree.printPostorder(); }}
输出:
Preorder traversal of binary tree is1 2 4 5 3 Inorder traversal of binary tree is4 2 5 1 3 Postorder traversal of binary tree is4 5 2 3 1
另外一个例子:
图片地址:https://www.cs.swarthmore.edu/~newhall/unixhelp/Java_bst.pdf
时间复杂度:O(n)
我们看下不同的边界情况。
函数复杂度 T(n) ——对于遍历说涉及到的所有问题——可以定义为:
T(n) = T(k) + T(n – k – 1) + c
这里根一边的节点的数目,n-k-1是另一边的节点数。
我们分析一下边界条件:
情况1:偏树(Skewed tree)(其中的一个子树为空,而另一边的子树不为空)。
这种情况下k等于0。
…………………………………………
………………………………………….
T(0)的值将是一个常数,比如d。(遍历一个空树的时间就是花费常量的时间)
情况2:左右子树的节点数目是相同的
这个递归函数对于大师级的方法( http://en.wikipedia.org/wiki/Master_theorem)是标准形式(
空间复杂度:如果我们不考虑栈的大小,那么函数调用是O(1) 否则是O(n)。
- 数据结构——二叉树的遍历
- 数据结构——二叉树的遍历
- 数据结构——二叉树的遍历
- 数据结构——二叉树的遍历
- 数据结构——二叉树的遍历
- 数据结构——二叉树的遍历
- 数据结构——树的遍历
- 数据结构——树的水平遍历
- 数据结构——树的遍历
- 数据结构——树的遍历
- 数据结构(5)——树及树的遍历
- Python数据结构——解析树及树的遍历
- 数据结构——二叉树的层次遍历
- 数据结构例程——二叉树遍历的递归算法
- 数据结构例程——二叉树的层次遍历算法
- 数据结构实践—— 二叉树遍历的递归算法
- 数据结构学习笔记——二叉树的遍历
- 数据结构—二叉树的遍历—递归
- 操作系统实践之第二章(特权级变换*实战篇)
- 智慧北京:handler机制
- Handler机制的原理
- Swift3.0学习笔记-Protocols
- 本地启动tomcat的时候报java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space
- 数据结构——树的遍历
- hdu1082
- Java 多线程(五) 多线程的同步
- SpringMVC 组件类大全
- android奇怪的bug记录
- 在Android中获取虚拟键盘高度的方法
- TCP状态转换图解析和应用
- Fresco强大的图片加载框架
- 使用Xcode的Instruments检测内存泄漏