数据结构-数组、链表、堆栈、队列

本文深入探讨了数据结构中的线性表,包括数组、链表、栈和队列的概念与操作。重点讲解了链表的层序遍历,以及递归实现的前序、中序和后序遍历。此外,还提到了数组的动态扩展和空间复杂度分析。栈的后入先出原则和队列的基本操作也在讨论范围内。
摘要由CSDN通过智能技术生成

目录

层序遍历

前序递归*********** 根结点--->左子树 ---> 右子树

中序递归***********左子树---> 根结点 ---> 右子树

后序递归***********左子树---> 右子树 ---> 根结点

​首先---线性表:

数组Array:

这种东西?☝☝☝ 

迭代法

递归法

栈(stack)也是线性的,后入先出原则;Push入栈与Pop出栈

队列(queue),只能在头尾操作。​


链表

层序遍历

在这里插入图片描述

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------二叉树详解

 

首先---线性表:

  1. 数组:顺序存储
  2. 链表
  3. 队列
  4. 哈希表(散列)

数组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啥的都行。。。之间有顺序,应用在前进后退!!!!!撤销恢复功能。

队列(queue),只能在头尾操作。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr.Thompson

相互学习,欢迎指正。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值