目录
前序递归*********** 根结点--->左子树 ---> 右子树
中序递归***********左子树---> 根结点 ---> 右子树
后序递归***********左子树---> 右子树 ---> 根结点
栈(stack)也是线性的,后入先出原则;Push入栈与Pop出栈
链表
层序遍历
public void levelOrder(node t) {//层序遍历
Queue<node> q1 = new ArrayDeque<node>();
if (t == null)
return;
if (t != null) {
q1.add(t);
}
while (!q1.isEmpty()) {
node t1 = q1.poll();
if (t1.left != null)
q1.add(t1.left);
if (t1.right != null)
q1.add(t1.right);
System.out.print(t1.value + " ");
}
System.out.println();
}
6.23.4.7.19.71.5.17.50.75
前序递归*********** 根结点--->左子树 ---> 右子树
public void preorderTraversal(node root)// 前序遍历:根结点 ---> 左子树 ---> 右子树
{
if (root!= null) {
System.out.print(root.value + " ");// 当前节点
preorderTraversal(root.left);
preorderTraversal(root.right);
}
}
public void inorderTraversal(node t)// 中序遍历:左子树---> 根结点 ---> 右子树
{
if (t != null) {
inorderTraversal(t.left);
System.out.print(t.value + " ");// 访问完左节点访问当前节点
inorderTraversal(t.right);
}
}
public void postorderTraversal(node t)// 后序遍历:左子树 ---> 右子树 ---> 根结点
{
if (t != null) {
postorderTraversal(t.left);
postorderTraversal(t.right);
System.out.print(t.value + " "); // 访问玩左右访问当前节点
}
}
中序递归***********左子树---> 根结点 ---> 右子树
后序递归***********左子树---> 右子树 ---> 根结点
https://www.jianshu.com/p/01192de8c21a
Java------Stack详解
https://www.jianshu.com/p/3587e59948a8
Java------二叉树详解
首先---线性表:
- 数组:顺序存储
- 链表
- 栈
- 队列
- 哈希表(散列)
数组Array:
当我们新建一个数组的时候,int arr[] = new int[] {11,12,13},此时的arr[]数组,局部变量存在栈空间,new出来的放在堆空间。
但是这个数组一旦声明了,容量不变了。所以需要设计动态数组,首先自己设计一个ArrayList,包含如下信息:
时间复杂度(time complexity):估算程序指令的执行次数(执行时间)
空间复杂度(space complexity):估算所需占用的存储空间
这种东西?☝☝☝
链表也是线性的,但链表不一定连续。
上几道面试题:
1,翻转链表:使用递归和迭代两种方式!
递归思路:传进去的 调用自身 搞清楚这个方法是干啥的,然后再去调用。
public class ReversLinkList(){
pbulic ListNode reverseList(ListNode head){
if(head == null||head.next==null){
return head;
}
ListNode newHead = reverseList(head.next);
head.next.next=head;
head.next=null;
return newHead;
}
}
非递归思路:
public class ReversLinkList2(){
pbulic ListNode reverseList(ListNode head){
if(head == null||head.next==null){
return head;
}
ListNode newHead = null;
while(head != null){
ListNode temp = head.next;
head.next=newHead;
newHead = head;
head = temp;
}
return newHead;
}
}
迭代法
从前到后开始反转,我们需要三个指针,第一个指针指向当前头结点 head,第二个指针指向第二个节点 curP(当前结点),第三个指针为保存下一个节点的临时节点 temp。
1、反转顺序为,先保存下一节点。
2、然后让当前结点的指向前一节点。
3、最后移动当前结点到下一结点。(head 头节点一开始初始化指向 null)。
4、重复该循环。
递归法
递归法只不过换了一个顺序,先递进去,然后在执行以上反转操作。
1、让当前结点的下一节点的下一节点指向当前结点。
2、当前节点的下一结点指向 null,直到递归完毕,完成反转。
//& 反转链表 - 迭代实现
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null) return null;
ListNode pre = null;
ListNode curP= head;
while(curP != null){
ListNode temp = curP.next;
curP.next = pre;
pre = curP;
curP = temp;
}
return pre;
}
}
//& 反转链表 — 递归实现
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null) return head;
ListNode tail = reverseList(head.next);
head.next.next = head;
head.next = null;
return tail;
}
}
BTree对节点的操作
import java.util.Stack;
public class BiTree {
private BiTree leftTree;
private BiTree rightTree;
private Object data;
public final static int MAX = 40;
BiTree[] elements = new BiTree[MAX];
int front;
int rear;
// 构造函数
public BiTree() {
// TODO Auto-generated constructor stub
}
public BiTree(Object data) {
this.data = data;
}
public BiTree(Object data, BiTree lefTree, BiTree righTree) {
this.data = data;
this.leftTree = lefTree;
this.rightTree = righTree;
}
// 递归前序遍历二叉树
public void preOrder(BiTree tree) {
if (tree != null) {
visit(tree.data);
preOrder(tree.leftTree);
preOrder(tree.rightTree);
}
}
// 非递归实现前序遍历
public void iterativePreOrder(BiTree tree) {
Stack<BiTree> stack = new Stack<BiTree>();
if (tree != null) {
stack.push(tree);
while (!stack.isEmpty()) {
tree = stack.pop();
visit(tree.data);
if (tree.rightTree != null)
stack.push(tree.rightTree);
if (tree.leftTree != null)
stack.push(tree.leftTree);
}
}
}
// 递归中序遍历二叉树
public void inOrder(BiTree tree) {
if (tree != null) {
inOrder(tree.leftTree);
visit(tree.data);
inOrder(tree.rightTree);
}
}
// 非递归实现中序遍历
public void iterativeInOrder(BiTree tree) {
Stack<BiTree> stack = new Stack<BiTree>();
while (tree != null) {
while (tree != null) {
if (tree.rightTree != null)
stack.push(tree.rightTree);// 当前节点右子入栈
stack.push(tree);// 当前节点入栈
tree = tree.leftTree;
}
tree = stack.pop();
while (!stack.empty() && tree.rightTree == null) {
visit(tree.data);
tree = stack.pop();
}
visit(tree.data);
if (!stack.empty())
tree = stack.pop();
else
tree = null;
}
}
// 递归后序遍历二叉树
public void postOrder(BiTree tree) {
if (tree != null) {
postOrder(tree.leftTree);
postOrder(tree.rightTree);
visit(tree.data);
}
}
// 非递归实现后序遍历
public void iterativePostOrder(BiTree tree) {
BiTree tempTree = tree;
Stack<BiTree> stack = new Stack<BiTree>();
while (tree != null) {
// 左子树入栈
for (; tree.leftTree != null; tree = tree.leftTree)
stack.push(tree);
// 当前节点无右子或右子已经输出
while (tree != null
&& (tree.rightTree == null || tree.rightTree == tempTree)) {
visit(tree.data);
tempTree = tree;// 记录上一个已输出节点
if (stack.empty())
return;
tree = stack.pop();
}
// 处理右子
stack.push(tree);
tree = tree.rightTree;
}
}
// 层次遍历二叉树
public void LayerOrder(BiTree tree) {
elements[0] = tree;
front = 0;
rear = 1;
while (front < rear) {
try {
if (elements[front].data != null) {
System.out.print(elements[front].data + " ");
if (elements[front].leftTree != null)
elements[rear++] = elements[front].leftTree;
if (elements[front].rightTree != null)
elements[rear++] = elements[front].rightTree;
front++;
}
} catch (Exception e) {
break;
}
}
}
// 求二叉树的高度
public static int height(BiTree tree) {
if (tree == null)
return 0;
else {
int leftTreeHeight = height(tree.leftTree);
int rightTreeHeight = height(tree.rightTree);
return leftTreeHeight > rightTreeHeight ? leftTreeHeight + 1
: rightTreeHeight + 1;
}
}
// 求data所对应结点的层数,如果对象不在树中,结果返回-1;否则结果返回该对象在树中所处的层次,规定根节点为第一层
public int level(Object data) {
int leftLevel, rightLevel;
if (this == null)
return -1;
if (data == this.data)
return 1;
leftLevel = leftTree == null ? -1 : leftTree.level(data);
rightLevel = rightTree == null ? -1 : rightTree.level(data);
if (leftLevel < 0 && rightLevel < 0)
return -1;
return leftLevel > rightLevel ? leftLevel + 1 : rightLevel + 1;
}
// 求二叉树的结点总数
public static int nodes(BiTree tree) {
if (tree == null)
return 0;
else {
int left = nodes(tree.leftTree);
int right = nodes(tree.rightTree);
return left + right + 1;
}
}
// 求二叉树叶子节点的总数
public static int leaf(BiTree tree) {
if (tree == null)
return 0;
else {
int left = leaf(tree.leftTree);
int right = leaf(tree.rightTree);
if (tree.leftTree == null && tree.rightTree == null)
return left + right + 1;
else
return left + right;
}
}
// 求二叉树父节点个数
public static int fatherNodes(BiTree tree) {
if (tree == null || (tree.leftTree == null && tree.rightTree == null))
return 0;
else {
int left = fatherNodes(tree.leftTree);
int right = fatherNodes(tree.rightTree);
return left + right + 1;
}
}
// 求只有一个孩子结点的父节点个数
public static int oneChildFather(BiTree tree) {
int left, right;
if (tree == null || (tree.rightTree == null && tree.leftTree == null))
return 0;
else {
left = oneChildFather(tree.leftTree);
right = oneChildFather(tree.rightTree);
if ((tree.leftTree != null && tree.rightTree == null)
|| (tree.leftTree == null && tree.rightTree != null))
return left + right + 1;
else
return left + right;/* 加1是因为要算上根节点 */
}
}
// 求二叉树只拥有左孩子的父节点总数
public static int leftChildFather(BiTree tree) {
if (tree == null)
return 0;
else {
int left = leftChildFather(tree.leftTree);
int right = leftChildFather(tree.rightTree);
if ((tree.leftTree != null && tree.rightTree == null))
return left + right + 1;
else
return left + right;
}
}
// 求二叉树只拥有右孩子的结点总数
public static int rightChildFather(BiTree tree) {
if (tree == null || tree.rightTree == null)
return 0;
else {
int left = rightChildFather(tree.leftTree);
int right = rightChildFather(tree.rightTree);
if (tree.leftTree == null && tree.rightTree != null)
return left + right + 1;
else
return left + right;
}
}
// 计算有两个节点的父节点的个数
public static int doubleChildFather(BiTree tree) {
int left, right;
if (tree == null)
return 0;
else {
left = doubleChildFather(tree.leftTree);
right = doubleChildFather(tree.rightTree);
if (tree.leftTree != null && tree.rightTree != null)
return (left + right + 1);/* 加1是因为要算上根节点 */
else
return (left + right);
}
}
// 访问根节点
public void visit(Object data) {
System.out.print(data + " ");
}
// 将树中的每个节点的孩子对换位置
public void exChange() {
if (this == null)
return;
if (leftTree != null)
leftTree.exChange();
if (rightTree != null)
rightTree.exChange();
BiTree temp = leftTree;
leftTree = rightTree;
rightTree = temp;
}
//递归求所有结点的和
public static int getSumByRecursion(BiTree tree){
if(tree==null){
return 0;
}
else{
int left=getSumByRecursion(tree.leftTree);
int right=getSumByRecursion(tree.rightTree);
return Integer.parseInt(tree.data.toString())+left+right;
}
}
//非递归求二叉树中所有结点的和
public static int getSumByNoRecursion(BiTree tree){
Stack<BiTree> stack = new Stack<BiTree>();
int sum=0;
if(tree!=null){
stack.push(tree);
while(!stack.isEmpty()){
tree=stack.pop();
sum+=Integer.parseInt(tree.data.toString());
if(tree.leftTree!=null)
stack.push(tree.leftTree);
if(tree.rightTree!=null)
stack.push(tree.rightTree);
}
}
return sum;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
BiTree e = new BiTree(5);
BiTree g = new BiTree(7);
BiTree h = new BiTree(8);
BiTree l = new BiTree(12);
BiTree m = new BiTree(13);
BiTree n = new BiTree(14);
BiTree k = new BiTree(11, n, null);
BiTree j = new BiTree(10, l, m);
BiTree i = new BiTree(9, j, k);
BiTree d = new BiTree(4, null, g);
BiTree f = new BiTree(6, h, i);
BiTree b = new BiTree(2, d, e);
BiTree c = new BiTree(3, f, null);
BiTree tree = new BiTree(1, b, c);
System.out.println("递归前序遍历二叉树结果: ");
tree.preOrder(tree);
System.out.println();
System.out.println("非递归前序遍历二叉树结果: ");
tree.iterativePreOrder(tree);
System.out.println();
System.out.println("递归中序遍历二叉树的结果为:");
tree.inOrder(tree);
System.out.println();
System.out.println("非递归中序遍历二叉树的结果为:");
tree.iterativeInOrder(tree);
System.out.println();
System.out.println("递归后序遍历二叉树的结果为:");
tree.postOrder(tree);
System.out.println();
System.out.println("非递归后序遍历二叉树的结果为:");
tree.iterativePostOrder(tree);
System.out.println();
System.out.println("层次遍历二叉树结果: ");
tree.LayerOrder(tree);
System.out.println();
System.out.println("递归求二叉树中所有结点的和为:"+getSumByRecursion(tree));
System.out.println("非递归求二叉树中所有结点的和为:"+getSumByNoRecursion(tree));
System.out.println("二叉树中,每个节点所在的层数为:");
for (int p = 1; p <= 14; p++)
System.out.println(p + "所在的层为:" + tree.level(p));
System.out.println("二叉树的高度为:" + height(tree));
System.out.println("二叉树中节点总数为:" + nodes(tree));
System.out.println("二叉树中叶子节点总数为:" + leaf(tree));
System.out.println("二叉树中父节点总数为:" + fatherNodes(tree));
System.out.println("二叉树中只拥有一个孩子的父节点数:" + oneChildFather(tree));
System.out.println("二叉树中只拥有左孩子的父节点总数:" + leftChildFather(tree));
System.out.println("二叉树中只拥有右孩子的父节点总数:" + rightChildFather(tree));
System.out.println("二叉树中同时拥有两个孩子的父节点个数为:" + doubleChildFather(tree));
System.out.println("--------------------------------------");
tree.exChange();
System.out.println("交换每个节点的左右孩子节点后......");
System.out.println("递归前序遍历二叉树结果: ");
tree.preOrder(tree);
System.out.println();
System.out.println("非递归前序遍历二叉树结果: ");
tree.iterativePreOrder(tree);
System.out.println();
System.out.println("递归中序遍历二叉树的结果为:");
tree.inOrder(tree);
System.out.println();
System.out.println("非递归中序遍历二叉树的结果为:");
tree.iterativeInOrder(tree);
System.out.println();
System.out.println("递归后序遍历二叉树的结果为:");
tree.postOrder(tree);
System.out.println();
System.out.println("非递归后序遍历二叉树的结果为:");
tree.iterativePostOrder(tree);
System.out.println();
System.out.println("层次遍历二叉树结果: ");
tree.LayerOrder(tree);
System.out.println();
System.out.println("递归求二叉树中所有结点的和为:"+getSumByRecursion(tree));
System.out.println("非递归求二叉树中所有结点的和为:"+getSumByNoRecursion(tree));
System.out.println("二叉树中,每个节点所在的层数为:");
for (int p = 1; p <= 14; p++)
System.out.println(p + "所在的层为:" + tree.level(p));
System.out.println("二叉树的高度为:" + height(tree));
System.out.println("二叉树中节点总数为:" + nodes(tree));
System.out.println("二叉树中叶子节点总数为:" + leaf(tree));
System.out.println("二叉树中父节点总数为:" + fatherNodes(tree));
System.out.println("二叉树中只拥有一个孩子的父节点数:" + oneChildFather(tree));
System.out.println("二叉树中只拥有左孩子的父节点总数:" + leftChildFather(tree));
System.out.println("二叉树中只拥有右孩子的父节点总数:" + rightChildFather(tree));
System.out.println("二叉树中同时拥有两个孩子的父节点个数为:" + doubleChildFather(tree));
}
}
栈(stack)也是线性的,后入先出原则;Push入栈与Pop出栈
ps:这个数据结构的栈和内存开发中的占空间不是一个概念,但有关系,要不为啥叫栈空间。。。
栈的实现:用ArrayList啥的都行。。。之间有顺序,应用在前进后退!!!!!撤销恢复功能。