数据结构(部分)

Posted 可乐好哇!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构(部分)相关的知识,希望对你有一定的参考价值。

栈、队列、二叉树详解(小白专属)

栈(Stack)

  •    概念:是一种特殊的线性表,只允许在固定的一端进行插入和删除元素操作,另一端称为栈底。它遵守先进后出的原则。

  • 代码实现:
    1.可以利用顺序表实现(使用尾插+尾删)稍微简单
    2. 可以利用链表实现(头尾都行)

public class MyStack 
   // 顺序表实现的栈
   public int[] elem = new int[100];
   public int usedSize = 0;

   public void push(int val) 
   		elem[usedSize] =  val;
   		usedSize++;
   

   public int pop() 
   		return	elem[--usedSize];
   

   public int peek() 
   		return	elem[usedSize - 1];
   

   public boolean isEmpty() 
   	return usedSize == 0;
   

   public int size() 
   	return usedSize;
   



队列(Queue)

  •   概念:只允许在一端插入数据操作,在另一端进行删除操作的特殊线性表,队列遵循先进先出的原则。


图解入队、出队过程:

  • 代码实现:
      队列也可以用数组和链表的结构实现,推荐使用链表实现,相当于尾插法(效率会更高)
class Node 
    public int val;
    public Node next;

    public Node(int val) 
        this.val = val;
    


public class MyQueue 

    public Node head = null;
    public Node tail = null;
    public int usedSize = 0;

    // 入队列(尾巴进)
    public void offer(int val) 
        Node node = new Node(val);
        if (this.tail == null) 
            this.head = node;
         else 
            this.tail.next = node;
        

        this.tail = node;
        this.usedSize++;
    

    // 出队列(脑袋出)(删除头)
    public int poll() 
        if (this.usedSize == 0) 
            throw new RuntimeException("队列为空!");
        

        Node oldHead = this.head;
        this.head = this.head.next;

        if (this.head == null) 
            this.tail = null;
        

        this.usedSize--;
        return oldHead.val;
    

    // 出队列(不删除)
    public int peek() 
        if (this.usedSize == 0) 
            throw new RuntimeException("队列为空!");
        
        return this.head.val;
    

    // 判断队列是否为空
    public boolean isEmpty() 
        return this.usedSize == 0;
    

    // 使用的队列空间大小
    public int size() 
        return this.usedSize;
    

二叉树

  • 概念:由一个根节点加上两颗别称左子树右子树的二叉树组成。

  • 特点:

    1. 每个节点最多有两颗子树,二叉树不存在大于2的结点

    2. 二叉树的子树有左右之分,子树的次序不能颠倒,二叉树是有序树

  • 存储:

    1. 顺序存储

    2. 类似于链表的链式存储

    // 孩子表示法(推荐使用)
    class Node 
    		int val;				// 数据
    		Node left;				// 左子树 
    		Node right;				// 右子树
    
    
    // 孩子双亲表示法
    class Node 
    		int val;				// 数据
    		Node left;				// 左子树 
    		Node right;				// 右子树
    		Node parent;			// 当前结点的根结点 
    
    
  • 遍历图示:

  • 代码实现(递归):

// 创建二叉树的结点
class TreeNode 

    int val;
    TreeNode left;
    TreeNode right;

    TreeNode() 
    

    TreeNode(int val) 
        this.val = val;
    

    TreeNode(int val, TreeNode left, TreeNode right) 
        this.val = val;
        this.left = left;
        this.right = right;
    

public class Solution() 
	// 前序遍历
    void preOrderTraversal(TreeNode root, List<Integer> res) 

        if (root == null) 
            return;
        

        res.add(root.val);
        preOrderTraversal(root.left, res);
        preOrderTraversal(root.right, res);

    

    // 中序遍历
    void inOrderTraversal(TreeNode root, List<Integer> res) 
        if (root == null) 
            return;
        

        preOrderTraversal(root.left, res);
        res.add(root.val);
        preOrderTraversal(root.right, res);

    

    // 后序遍历
    void postOrderTraversal(TreeNode root, List<Integer> res) 

        if (root == null) 
            return;
        

        postOrderTraversal(root.left, res);
        postOrderTraversal(root.right, res);
        res.add(root.val);
    

    // 子问题思路-求结点个数
    int getSize(TreeNode root) 
        if (root == null) 
            return 0;
        

        return getSize(root.left) + getSize(root.right);
    

    // 子问题思路-求叶子结点个数
    int getLeafSize(TreeNode root) 
        if (root == null) 
            return 0;
        

        if (root.left == null && root.right == null) 
            return 1;
        

        return getLeafSize(root.left) + getLeafSize(root.right);
    

    // 子问题思路-求第 k 层结点个数
    int getKLevelSize(TreeNode root, int k) 
        if (root == null) 
            return 0;
        

        if (k == 1) 
            return 1;
        

        return getKLevelSize(root.left, k - 1) + getKLevelSize(root.right, k - 1);
    

    // 获取二叉树的高度
    int getHeight(TreeNode root) 
        if (root == null) 
            return 0;
        

        int l = getHeight(root.left);
        int r = getHeight(root.right);

        return l > r ? l + 1 : r + 1;
    

    // 查找 val 所在结点,没有找到返回 null
    // 按照 根 -> 左子树 -> 右子树的顺序进行查找
    // 一旦找到,立即返回,不需要继续在其他位置查找
    TreeNode find(TreeNode root, int val) 
        if (root == null) 
            return null;
        

        TreeNode l = find(root.left, val);
        if (l != null) 
            return l;
        

        TreeNode r = find(root.right, val);
        if (r != null) 
            return r;
        

        return null;
    

    // 比较两个二叉树是否相同
    public boolean isSameTree(TreeNode p, TreeNode q) 

        if (p == null && q == null) 
            return true;
        

        if (p == null && q != null || p != null && q == null) 
            return false;
        

        if (p.val != q.val) 
            return false;
        

        return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);

    

    // 合并两个二叉树
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) 

        // 如果root1为空 则使用root2的根
        if (root1 == null) 
            return root2;
        
        // 同上
        if (root2 == null) 
            return root1;
        

        // 都存在结点 就返回两个结点的和
        TreeNode node = new TreeNode(root1.val + root2.val);

        // 进行递归调用
        node.left = mergeTrees(root1.left, root2.left);
        node.right = mergeTrees(root1.right, root2.right);

        return node;
    


  • 代码实现(非递归):
 	//前序遍历
    public List<Integer> preorderTraversal(TreeNode root) 

        // 创建一个接收结果的ArrayList
        List<Integer> res = new ArrayList<>();

        if (root == null) 
            return res;
        

        // 创建一个栈
        Stack<TreeNode> stack = new Stack<>();

        //定义一个node等于root
        TreeNode node = root;

        while (!stack.isEmpty() || node != null) 

            while (node != null) 
                res.add(node.val);
                stack.push(node);
                node = node.left;
            

            node = stack.pop();
            node = node.right;

        
        return res;
    

    //中序遍历
    public List<Integer> inorderTraversal(TreeNode root) 

        List<Integer> res = new ArrayList<>();

        Stack<TreeNode> stack = new Stack<>();

        TreeNode node = root;

        while (node != null || !stack.isEmpty()) 

            while (node != null) 

                stack.push(node);
                node = node.left;

            

            node = stack.pop();
            res.add(node.val);
            node = node.right;

        
        return res;
    

    //后序遍历
    public List<Integer> postorderTraversal(TreeNode root) 

        List<Integer> res = new ArrayList<>();

        Stack<TreeNode> stack = new Stack<>();

        if (root == null) 
            return res;
        

        TreeNode node = root;
        TreeNode prevNode = null;

        while (node != null || !stack.isEmpty()) 

            while (node != null) 
                stack.push(node);
                node = node.left;
            

            node = stack.pop();

            if (node.right == null || node.right == prevNode) 
                res.add(node.val);
                prevNode = node;
                node = null;
             else 
                stack.push(node);
                node = node.right;
            

        
        return res;
    

	// 层序遍历
	public void levelOrderTraversal(TreeNode root) 

        if (root == null) 
            return;
        

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

        while (!queue.isEmpty()) 

            TreeNode cur = queue.poll();
            System.out.println(cur.val + " ");

            if (cur.left != null) 
                queue.offer(cur.left);
            

            if (cur.right != null) 
                queue.offer(cur.right);
            

        

    

补充

层序遍历(代码如上所述,过程图如下所示):
         从所在二叉树的根结点出发,首先访问第一层的树根节点,然后从左到右访问第二层上的节点,接着依次往后推,自上而下,自左至右逐层访问数的节点的过程就是程序遍历

不好之处请多多留言指点!!!

以上是关于数据结构(部分)的主要内容,如果未能解决你的问题,请参考以下文章

python数据结构之二叉树的遍历实例

二叉树的遍历

二叉树

浅谈数据结构-二叉树

浅谈数据结构-二叉树

数据结构 二叉树