数据结构(部分)
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);
补充
层序遍历(代码如上所述,过程图如下所示):
从所在二叉树的根结点出发,首先访问第一层的树根节点,然后从左到右访问第二层上的节点,接着依次往后推,自上而下,自左至右逐层访问数的节点的过程就是程序遍历。
不好之处请多多留言指点!!!
以上是关于数据结构(部分)的主要内容,如果未能解决你的问题,请参考以下文章