读书笔记-《数据结构与算法》-摘要1[数据结构]

文章目录

  • [数据结构]
    • 1. String - 字符串
    • 2. Linked List - 链表
      • 2.1 链表的基本操作
      • 2.1.1 反转链表
        • 单向链表
        • 双向链表
      • 2.1.2 删除链表中的某个节点
      • 2.1.3 链表指针的鲁棒性
      • 2.1.4 快慢指针
    • 3. Binary Tree - 二叉树
      • 3.1 树的遍历
      • 3.2 Binary Search Tree - 二叉查找树
    • 4. Queue - 队列
      • 4.1 Queue - 队列
      • 4.2 Priority Queue - 优先队列
      • 4.3 Deque - 双端队列
    • 5. Heap - 堆
    • 堆的基本操作
    • 6. Stack - 栈
    • 7. Set
    • 8. Map - 哈希表
    • 9. Graph - 图

[数据结构]

1. String - 字符串

开发常用,没啥可说的,注意的是字符串拼接时,可能会用到 StringBuffer 与 StringBuilder,前者保证线程安全,后者不是,但单线程下效率高一些,一般使用 StringBuilder。

2. Linked List - 链表

链表是线性表的一种。线性表是最基本、最简单、也是最常用的一种数据结构。

线性表有两种存储方式,一种是顺序存储结构(例如数组),另一种是链式存储结构。

链式存储结构就是两个相邻的元素在内存中可能不是相邻的,每一个元素都有一个指针域,指针域一般是存储着到下一个元素的指针。这种存储方式的优点是插入和删除的时间复杂度为 O(1),缺点是访问的时间复杂度最坏为 O(n)。

链表就是链式存储的线性表。根据指针域的不同,链表分为单向链表、双向链表、循环链表等等。

2.1 链表的基本操作

2.1.1 反转链表

单向链表

链表的基本形式是:1 -> 2 -> 3 -> null,反转需要变为 3 -> 2 -> 1 -> null。这里要注意:

  • 访问某个节点 curt.next 时,要检验 curt 是否为 null。
  • 要把反转后的最后一个节点(即反转前的第一个节点)指向 null。
class ListNode {
    int val;
    ListNode next;
    ListNode(int val) {
        this.val = val;
    }
}

public ListNode reverse(ListNode head) {
    ListNode prev = null;
    while (head != null) {
        ListNode next = head.next;
        head.next = prev;
        prev = head;
        head = next;
    }
    return prev;
}
双向链表

和单向链表的区别在于:双向链表的反转核心在于nextprev域的交换,还需要注意的是当前节点和上一个节点的递推。

class DListNode {
    int val;
    DListNode prev, next;
    DListNode(int val) {
        this.val = val;
        this.prev = this.next = null;
    }
}

public DListNode reverse(DListNode head) {
    DListNode curr = null;
    while (head != null) {
        curr = head;
        head = curr.next;
        curr.next = curr.prev;
        curr.prev = head;
    }
    return curr;
}

2.1.2 删除链表中的某个节点

删除链表中的某个节点一定需要知道这个点的前继节点,所以需要一直有指针指向前继节点。还有一种删除是伪删除,是指复制一个和要删除节点值一样的节点,然后删除,这样就不必知道其真正的前继节点了。

然后只需要把 prev -> next = prev -> next -> next 即可。

2.1.3 链表指针的鲁棒性

综合上面讨论的两种基本操作,链表操作时的鲁棒性问题主要包含两个情况:

  • 当访问链表中某个节点 curt.next 时,一定要先判断 curt 是否为 null。
  • 全部操作结束后,判断是否有环;若有环,则置其中一端为 null

2.1.4 快慢指针

所谓快慢指针中的快慢指的是指针向前移动的步长,每次移动的步长较大即为快,步长较小即为慢,常用的快慢指针一般是在单链表中让快指针每次向前移动2,慢指针则每次向前移动1。快慢两个指针都从链表头开始遍历,于是快指针到达链表末尾的时候慢指针刚好到达中间位置,于是可以得到中间元素的值。快慢指针在链表相关问题中主要有两个应用:

  • 快速找出未知长度单链表的中间节点 设置两个指针 *fast*slow 都指向单链表的头节点,其中*fast的移动速度是*slow的2倍,当*fast指向末尾节点的时候,slow正好就在中间了。
  • 判断单链表是否有环 利用快慢指针的原理,同样设置两个指针 *fast*slow 都指向单链表的头节点,其中 *fast的移动速度是*slow的2倍。如果 *fast = NULL,说明该单链表 以 NULL结尾,不是循环链表;如果 *fast = *slow,则快指针追上慢指针,说明该链表是循环链表。

3. Binary Tree - 二叉树

二叉树是每个节点最多有两个子树的树结构,子树有左右之分,二叉树常被用于实现二叉查找树二叉堆

public class TreeNode {
    public int val;
    public TreeNode left, right;
    public TreeNode(int val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
}

3.1 树的遍历

从二叉树的根节点出发,节点的遍历分为三个主要步骤:对当前节点进行操作(称为“访问”节点,或者根节点)、遍历左边子节点、遍历右边子节点。访问节点顺序的不同也就形成了不同的遍历方式。需要注意的是树的遍历通常使用递归的方法进行理解和实现,在访问元素时也需要使用递归的思想去理解。实际实现中对于前序和中序遍历可尝试使用递归实现。

按照访问根元素(当前元素)的前后顺序,遍历方式可划分为如下几种:

  • 深度优先:先访问子节点,再访问父节点,最后访问第二个子节点。根据根节点相对于左右子节点的访问先后顺序又可细分为以下三种方式。
    1. 前序(pre-order):先根后左再右
    2. 中序(in-order):先左后根再右
    3. 后序(post-order):先左后右再根
  • 广度优先:先访问根节点,沿着树的宽度遍历子节点,直到所有节点均被访问为止。

3.2 Binary Search Tree - 二叉查找树

一颗二叉查找树(BST)是一颗二叉树,其中每个节点都含有一个可进行比较的键及相应的值,且每个节点的键都大于等于左子树中的任意节点的键,而小于右子树中的任意节点的键

使用中序遍历可得到有序数组,这是二叉查找树的又一个重要特征。

二叉查找树使用的每个节点含有两个链接,它是将链表插入的灵活性和有序数组查找的高效性结合起来的高效符号表实现。

4. Queue - 队列

4.1 Queue - 队列

Queue 是一个 FIFO(先进先出)的数据结构,并发中使用较多,可以安全地将对象从一个任务传给另一个任务。

Queue 在 Java 中是 Interface, 一种实现是 LinkedList 向上转型为 Queue, Queue 通常不能存储 null 元素,否则与 poll() 等方法的返回值混淆。

Queue<Integer> q = new LinkedList<Integer>();
int qLen = q.size(); // get queue length
0:0Throws exceptionReturns special value
Insertadd(e)offer(e)
Removeremove()poll()
Examineelement()peek()

优先考虑右侧方法,右侧元素不存在时返回 null. 判断非空时使用isEmpty()方法,继承自 Collection.

import java.util.LinkedList;
import java.util.Queue;

public class QueueMethods {
    public static void main(String[] args) {
        Queue<Integer> q = new LinkedList<>();
        q.offer(1); // 增加元素
        q.offer(2); // 增加元素
        q.add(3); // 增加元素
        q.add(4); // 增加元素
        int size = q.size(); // 获取长度
        System.out.println("原始 q:" + q);

        /*
         * remove 移除 Queue 的头部元素,并返回移除的元素
         * 移除时若队列为空,则报错:NoSuchElementException
         * 这也是它与 pull 方法的区别
         */
        Integer remove = q.remove();
        System.out.println("remove 后 获取的元素 remove:" + remove);
        System.out.println("remove 后 q:" + q);

        Integer poll = q.poll();
        System.out.println("poll 后 获取的元素 poll:" + poll);
        System.out.println("poll 后 q:" + q);

        /*
         * element 获取 Queue 的头部元素,并返回移除的元素
         * 移除时若队列为空,则报错:NoSuchElementException
         * 这也是它与 peek 方法的区别
         */
        Integer element = q.element();
        System.out.println("element 后 获取的元素 element:" + element);
        System.out.println("element 后 q:" + q);

        Integer peek = q.peek();
        System.out.println("peek 后 获取的元素 peek:" + peek);
        System.out.println("peek 后 q:" + q);

        // 判断队列是否为空
        boolean empty = q.isEmpty();
        System.out.println("q 是否为空:" + empty);
    }
}

输出:

原始 q:[1, 2, 3, 4]
remove 后 获取的元素 remove:1
remove 后 q:[2, 3, 4]
poll 后 获取的元素 poll:2
poll 后 q:[3, 4]
element 后 获取的元素 element:3
element 后 q:[3, 4]
peek 后 获取的元素 peek:3
peek 后 q:[3, 4]
q 是否为空:false

在这里插入图片描述

(图网,侵删)

4.2 Priority Queue - 优先队列

应用程序常常需要处理带有优先级的业务,优先级最高的业务首先得到服务。因此优先队列这种数据结构应运而生。优先队列中的每个元素都有各自的优先级,优先级最高的元素最先得到服务;优先级相同的元素按照其在优先队列中的顺序得到服务。

优先队列可以使用数组或链表实现,从时间和空间复杂度来说,往往用二叉堆来实现。

Java 中提供PriorityQueue类,该类是 Interface Queue 的另外一种实现,和LinkedList的区别主要在于排序行为而不是性能,基于 priority heap 实现,非synchronized,故多线程下应使用PriorityBlockingQueue. 默认为自然序(小根堆),需要其他排序方式可自行实现Comparator接口,选用合适的构造器初始化。使用迭代器遍历时不保证有序,有序访问时需要使用Arrays.sort(pq.toArray()).

4.3 Deque - 双端队列

双端队列(deque,全名double-ended queue)可以让你在任何一端添加或者移除元素,因此它是一种具有队列和栈性质的数据结构。

Java 在1.6之后提供了 Deque 接口,既可使用ArrayDeque(数组)来实现,也可以使用LinkedList(链表)来实现。前者是一个数组外加首尾索引,后者是双向链表。

Deque<Integer> deque = new ArrayDeque<Integer>();
First Element (Head)Last Element (Tail)
Throws exceptionSpecial valueThrows exceptionSpecial value
InsertaddFirst(e)offerFirst(e)addLast(e)offerLast(e)
RemoveremoveFirst()pollFirst()removeLast()pollLast()
ExaminegetFirst()peekFirst()getLast()peekLast()

其中offerLast和 Queue 中的offer功能相同,都是从尾部插入。

5. Heap - 堆

一般情况下,堆通常指的是二叉堆二叉堆是一个近似完全二叉树的数据结构,即披着二叉树羊皮的数组,故使用数组来实现较为便利。子结点的键值或索引总是小于(或者大于)它的父节点,且每个节点的左右子树又是一个二叉堆(大根堆或者小根堆)。根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆。常被用作实现优先队列。

堆的基本操作

以大根堆为例,堆的常用操作如下。

  1. 最大堆调整(Max_Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
  2. 创建最大堆(Build_Max_Heap):将堆所有数据重新排序
  3. 堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算

其中步骤1是给步骤2和3用的。

—PS:这本书里有很多这种动图,简直就是神器

6. Stack - 栈

栈是一种 LIFO(Last In First Out) 的数据结构,常用方法有添加元素,取栈顶元素,弹出栈顶元素,判断栈是否为空。

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Stack;

public class StackMethods {
    public static void main(String[] args) {
        /*
         * JDK doc 中建议使用Deque代替Stack实现栈,
         * 因为Stack继承自Vector,需要synchronized,性能略低。
         */
        Stack<Integer> stack = new Stack<>();
        Deque<Integer> s = new ArrayDeque<>();

        // E push(E item) - 向栈顶添加元素
        s.push(1);
        s.push(2);
        s.push(3);
        System.out.println("原始栈:" + s);
        System.out.println("原始栈,长度:" + s.size());

        // E peek() - 取栈顶元素,不移除
        Integer peek = s.peek();
        System.out.println("获取的栈顶元素:" + peek);
        System.out.println("peek 栈,长度:" + s.size());

        // E pop() - 移除栈顶元素并返回该元素
        Integer pop = s.pop();
        System.out.println("获取的栈顶元素:" + pop);
        System.out.println("pop 栈,长度:" + s.size());

        // 判断栈是否为空,若使用 Stack 类构造则为 empty()
        System.out.println("Deque 创建栈是否为空:" + s.isEmpty());
        System.out.println("Stack 创建栈是否为空:" + stack.empty());
    }
}

输出:

原始栈:[3, 2, 1]
原始栈,长度:3
获取的栈顶元素:3
peek 栈,长度:3
获取的栈顶元素:3
pop 栈,长度:2
Deque 创建栈是否为空:false
Stack 创建栈是否为空:true

7. Set

Set 是一种用于保存不重复元素的数据结构。常被用作测试归属性,故其查找的性能十分重要。

Set 与 Collection 具有安全一样的接口,通常有HashSet, TreeSetLinkedHashSet三种实现。HashSet基于散列函数实现,无序,查询速度最快;TreeSet基于红-黑树实现,有序。

8. Map - 哈希表

Map 是一种关联数组的数据结构,也常被称为字典或键值对。

Java 的实现中 Map 是一种将对象与对象相关联的设计。常用的实现有HashMapTreeMap, HashMap被用来快速访问,而TreeMap则保证『键』始终有序。Map 可以返回键的 Set, 值的 Collection, 键值对的 Set.

Map<String, Integer> map = new HashMap<String, Integer>();
map.put("bill", 98);
map.put("ryan", 99);
boolean exist = map.containsKey("ryan"); // check key exists in map
int point = map.get("bill"); // get value by key
int point = map.remove("bill") // remove by key, return value
Set<String> set = map.keySet();
// iterate Map
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    String key = entry.getKey();
    int value = entry.getValue();
    // do some thing
}

9. Graph - 图

图的表示通常使用邻接矩阵和邻接表,前者易实现但是对于稀疏矩阵会浪费较多空间,后者使用链表的方式存储信息但是对于图搜索时间复杂度较高。

/* Java Definition */
int[][] g = new int[V][V];

在这里插入图片描述
(图网,侵删)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/209020.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JDK21无法导入TimeUnit类

运行环境&#xff1a;windows11、IDEA2023.1.3、JDK21 问题描述&#xff1a;IDEA中无法导入java.util.concurrent.TimeUnit类。 以下截图是问题解决后的截图。有问题的时候未截图&#xff0c;说明一下&#xff0c;有问题的时候TimeUnit类是红色的&#xff0c;无法导入&#x…

申请开通QMT量化需要多少资金?免费开通!

最近量化交易在市场上大火&#xff0c;很多投资者想要参与进来。QMT量化软件是目前市场上一款比较常见并且强大的量化软件。那开通QMT量化交易软件需要多少资金&#xff1f; QMT量化交易软件是一种专门用于量化交易的工具&#xff0c;它能够帮助投资者通过程序化交易策略进行股…

布隆过滤器

目录 布隆过滤器的提出 布隆过滤器的概念 布隆过滤器的实现 布隆过滤器的插入 布隆过滤器的查找 布隆过滤器的删除 布隆过滤器的优点 布隆过滤器的缺点 布隆过滤器的使用场景 布隆过滤器的提出 在注册账号设置昵称的时候,为了保证每个用户的昵称唯一性,系统必须检测…

庆科EMW3080wifi模组烧录AT固件

本文记录庆科的EMW3080wifi模组烧写AT固件的过程&#xff1b; 参考文档&#xff1a;https://mxchip.yuque.com/zc9vym/tn0rwo/kgs4lx?singleDoc#NrlEB 以上链接为庆科方提供的文档&#xff0c;如有侵权立即删除&#xff1b; 庆科官方提供了三种烧录方式&#xff0c;我这边只记…

Quirks(怪癖)模式是什么?它和 Standards(标准)模式有什么区别?

前言: "Quirks模式"和"Standards模式"是与HTML文档渲染模式相关的两种模式。它们影响着浏览器如何解释和渲染HTML和CSS。理解它们之间的区别对于前端开发者和网页设计师来说是至关重要的。本文将深入讨论Quirks模式和Standards模式的区别&#xff0c;以及它…

如何快速了解一家公司?

在炒股过程中&#xff0c;我们想要了解一家公司是否具有投资价值&#xff0c;需要查看和阅读很多公司的相关资料。股民们自行去查询往往会花费很多的时间精力&#xff0c;所以专业的炒股软件一般都会给股民提供这些现成的资料。 在金斗云智投APP内&#xff0c;进入到个股详情页…

知识管理平台Confluence:win10安装confluence

文章目录 介绍主要功能 安装教程安装java运行平台JRE安装数据库Postgresql在Postgresql创建confluence使用的数据库创建数据库用户创建数据库 安装confluence注册confluence启动confluence 参考链接 介绍 Confluence 是由澳大利亚软件公司 Atlassian 开发的企业协作平台。它提…

负电源电压转换-TP7660H

负电源电压转换-TP7660H 简介引脚说明典型应用电路倍压与反压的应用电路 简介 TP7660H 是一款 DC/DC 电荷泵电压反转器专用集成电路。芯片能将输入范围为 2.5V&#xff5e;11V 的电压转换成相应的-2.5V&#xff5e;-11V 的输出&#xff0c;电压转换精度可达99.9%&#xff0c;电…

2022年高校大数据挑战赛B题图像信息隐藏求解全过程论文及程序

2022年高校大数据挑战赛 B题 图像信息隐藏 原题再现&#xff1a; 互联网的快速发展&#xff0c;给图像、视频的传播方式带来巨大变化。图像作为媒体的重要载体&#xff0c;每天有大量的原创图像公开在互联网上&#xff0c;如何保护图像版权的同时不破坏原始的图像一直是图像处…

MySQL 索引,优化,回表,执行计划等相关总结学习

一、MySQL 执行流程 innoDB表引擎&#xff1a;默认的事务型引擎&#xff0c;最重要最广泛的存储引擎&#xff0c;性能非常优秀,数据村粗在共享表空间&#xff0c;可以通过配置分开,主键查询性能高于其他引擎 myISM表引擎&#xff1a;5.1版本前这个是默认的存储引擎&#xff0c…

inBuilder低代码平台新特性推荐-第十二期

各位CSDN的友友们&#xff0c;大家好~ 今天来给大家介绍一下inBuilder低代码平台社区版中特性推荐系列第十二期——新版本集成开发环境&#xff01; 01 概述 编码规则定义规定了编号的生成格式&#xff0c;一条编码规则定义由基本信息和段列表组成&#xff1a;基本信息是对该编…

OCR原理解析

目录 1.概述 2.应用场景 3.发展历史 4.基于传统算法的OCR技术原理 4.1 图像预处理 4.1.1 灰度化 4.1.2 二值化 4.1.3 去噪 4.1.4 倾斜检测与校正 4.1.4.2 轮廓矫正 4.1.5 透视矫正 4.2 版面分析 4.2.1 连通域检测文本 4.2.2 MSER检测文本 4.3 字符切割 4.3.1 连…

视频后期特效处理软件 Motion 5 mac中文版

Motion mac是一款运动图形和视频合成软件&#xff0c;适用于Mac OS平台。 Motion mac软件特点 - 精美的效果&#xff1a;Motion提供了多种高质量的运动图形和视频效果&#xff0c;例如3D效果、烟雾效果、粒子效果等&#xff0c;方便用户制作出丰富多彩的视频和动画。 - 高效的工…

【力扣 面试题02.07链表相交】一种思路极其清晰的解法

力扣一单简单题&#xff0c;看完大佬的题解真是佩服得五体投地&#xff01; 虽是一道简单题&#xff0c;当我吭哧吭哧写了几十行后&#xff0c;看到大佬仅仅几行直接秒掉&#xff0c;只能说算法的本质还是数学&#xff0c;数学逻辑思维真是太重要了&#xff0c;有时候真得慢慢去…

TZOJ 1429 小明A+B

答案&#xff1a; #include <stdio.h> int main() {int T0, A0, B0, sum0;scanf("%d", &T); //输入测试数据的组数while (T--) //循环T次{scanf("%d %d", &A, &B); //输入AB的值sum A B;if (sum > 100) //如果是三位数{…

使用 Go 构建高性能的命令行工具

命令行工具&#xff08;CLI&#xff09;在软件开发中扮演着重要的角色&#xff0c;尤其是在自动化工具、开发工具链和服务器管理等领域。Go 语言以其简洁性和高性能而闻名&#xff0c;非常适合用来创建强大且高效的 CLI 工具。本文将详细介绍如何使用 Go 语言来构建 CLI 应用&a…

基于hadoop下的hbase安装

简介 HBase是一个分布式的、面向列的开源数据库&#xff0c;该技术来源于Fay Chang所撰写的Google论文“Bigtable&#xff1a;一个结构化数据的分布式存储系统”。就像Bigtable利用了Google文件系统&#xff08;File System&#xff09;所提供的分布式数据存储一样&#xff0c;…

Python批量Git Pull,对文件夹批量进行Pull操作

效果展示 说明 本来是想写的完善一些&#xff0c;但由于是自用&#xff0c;所以写出来后发现已经解决了自己的问题&#xff0c;所有 2和3功能没有写。 执行的话&#xff0c;需要 cmd 之后 直接 Python BatchGitPull.py 运行下面代码即可。 里面同时涉及到其他Pyhon知识点(写给…

SSM项目实战-mapper实现

1、SysUserMapper.java package com.atguigu.schedule.mapper; import com.atguigu.schedule.pojo.SysUser; import org.springframework.stereotype.Repository; Repository public interface SysUserMapper {SysUser getSysUser(SysUser sysUser); }2、ScheduleMapper.java p…

“超越摩尔定律”,存内计算走在爆发的边缘

过去几十年来&#xff0c;在摩尔定律的推动下&#xff0c;处理器的性能有了显著提高。然而&#xff0c;传统的计算架构将数据的处理和存储分离开来&#xff0c;随着以数据为中心的计算&#xff08;如机器学习&#xff09;的发展&#xff0c;在这两个物理分离的单元之间传输数据…