热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

集合框架(1)

集合框架(1)数据结构是了解数据存储在内存中的顺序和位置关系;算法是为求解一个问题所需要遵循的、被清楚指定的简单指令的集合。数据结构是为

集合框架(1)

数据结构是了解数据存储在内存中的顺序和位置关系;算法是为求解一个问题所需要遵循的、被清楚指定的简单指令的集合。数据结构是为算法服务的,算法是要作用在特定的数据结构上的。

常见的数据结构与算法:

数据结构:数组、链表、栈和队列、散列表hash、二叉树、堆、跳表、图

算法:递归、排序(学习七种和三种扩展,冒泡和快排必须掌握)、搜索、哈希、贪心、分治、回溯、动态规划、字符串匹配


学习方法

记忆接口中的方法,记忆对应接口的实现类(区别和如何选择,选择的原因是学习的重点)

集合框架


  1. 如何持有一组数据最合理
  2. 程序 = 数据结构 (如何持有数据)+ 算法(如何解决问题)
  3. https://www.cs.usfca.edu/~galles/visualization/Algorithms.html

衡量算法:时间和空间的选择

复杂度分析,快和省的问题,引入O复杂度表示法,表示代码的执行时间苏浙数据规模的变化趋势

​ O(1) 常量级 O(logN)(估算,并不是精确计算)对数阶 O(n^m)指数阶


递归


  1. 待求解问题可分解成几个子问题;
  2. 待求解问题与分解和的子问题只有数据规模不同,求解思路一致
  3. 存在递归终止条件

练习:假设有n级台阶,人可以每步跨1级或者2级台阶,上这n级台阶有多少种方法

思路:f(n) = f(n-1) + f(n-2) 终止条件 f(1) = 2 f(2) = 2

编程实现:找到将大的问题分解为小问题的规律,并且基于此规律写出递推公式,然后推导出终止条件,最后将递推公式和终止条件编译成代码

public static int up(int num) {if (num == 1) {return 1;}if (num == 2) {return 2;}if (num > 3) {return up(num - 1) + up(num - 2);}return 0;}public static void main(String[] args) {int a = up(10);System.out.println(a);}

问题


  1. 堆栈溢出。由于函数调用会使用函数调用栈来保存当前的运行现场,但是系统栈或者虚拟机栈一般不会太大,所以如果递归求解的数据规模很大,调用层次很深,可能导致栈溢出 StackOverflowError
  2. 重复计算问题。可以引入备忘录保存已经求解的结果,典型的以浪费内存为代价换取高执行效率

数组

数组(本身是一种引用类型):一组相关类型的变量集合,这些变量可以按照统一下标的方式进行操作,是一种典型的线性结构

特性:


  • 随机访问。支持在O(1)内按照下标进行快速访问元素
  • 插入和删除数据可能会有数据移动问题。时间复杂度是O(n)
  • 警惕数据访问越界问题ArrayIndexOutOfBoundsException

数组的基本使用


  • 声明。int[] arr 或者 int arr[]
  • 分配空间。数组空间是连续的,arr = new int[10],java不支持变长数组,如果需要变长则需要自行编程实现
  • 赋值。元素都有默认值。
  • 处理。可以通过下标对数组元素进行操作

排序算法1

排序算法的衡量标准:


  • 时间复杂度
  • 空间复杂度
  • 稳定性

Java中的排序算法:冒泡、插入、选择、快速、哈希、归并、堆…


冒泡排序

核心思想:相邻比较,交换位置

空间复杂度O(1)、时间复杂度O(n^2(两级for循环嵌套))、稳定

public static void main(String[] args) {int[] arr &#61; { 2, 21, 49, 17, 50, 1 };for (int i &#61; 0; i < arr.length - 1; i&#43;&#43;) {for (int j &#61; 0; j < arr.length - 1 - i; j&#43;&#43;) {if (arr[j] > arr[j &#43; 1]) {int tmp &#61; arr[j];arr[j] &#61; arr[j &#43; 1];arr[j &#43; 1] &#61; tmp;}}}System.out.println(Arrays.toString(arr));}

快速排序

核心思想&#xff1a;通过一次排序将数据序列分成左右两个部分&#xff0c;其中左半部分的值都比右半部分的值小&#xff0c;然后再分别对左右部分的数据进行排序&#xff0c;直到整个数据序列有序

空间复杂度O(1)、时间复杂度O(nlongn)、不稳定


数据结构概述

基本数据结构3种&#xff1a;线性表、树、图


线性表

线性表是一种线性结构&#xff0c;是由零个或者多个数据元素构成的有序序列。

特征&#xff1a;除了头尾元素&#xff0c;每个元素有且只有一个直接前驱和一个直接后继&#xff1b;而头元素&#xff0c;没有直接前驱&#xff0c;尾元素没有直接后继

常见的线性结构有数组和链表结构


数组

存储区域是连续的&#xff0c;占用内存比较严重&#xff0c;所以空间复杂度较大&#xff0c;但是&#xff08;必须先进行排序&#xff09;可以使用二分法查找元素&#xff0c;时间复杂度较小

特点&#xff1a;


  • 地址方便&#xff0c;时间复杂度O(1)
  • 插入和删除比较困难&#xff0c;可能会引发元素移动&#xff0c;时间复杂度O(n)
  • java中的数组是定长的&#xff0c;如果需要变长则需要自行编程实现&#xff08;可使用System.arrayCopy方法&#xff09;

链表

数组需要一块连续的内存空间存储数据&#xff0c;对内存要求较高。而链表通过指针可以将一组零散的内存块串联起来使用。

数组擅长按照下标进行随机访问&#xff0c;链表擅长删除、插入操作

具体实现&#xff1a;在链表中使用节点存储数据&#xff0c;并使用引用串联各个元素。每个节点除了存储数据本身之外还需要额外存储下一个节点的地址


单向链表

public class Node{private int date;//存储集体数据private Node next;//记录下一个节点的作用&#xff0c;尾节点指向null}

创建2个节点的流程

Node node1 &#61; new Node();
node1.setDate(123);//具体存储数据&#xff0c;next此时为null&#xff1b;所以node1是一个尾节点Node node2 &#61; new Node();
node2.setDate(456);
node1.setNext(node2);//使node1的下一个元素指针指向到node2对象

Link的实现

public class linkList{private Node head &#61; null;//整个链表的头指针public static class Node{private int date;private Node next;}
}

新增数据

public void insert(Node a,Node b){//在节点a后面插入新节点bif(a &#61;&#61; null){//在链表的头部添加数据bb.next &#61; head;head &#61; b;}else {b.next &#61; a.next;a.next &#61; b;}
}

删除数据

// 删除已知前驱节点为a的节点b&#xff0c;b的前驱节点为apublic void remove(Node a, Node b) {// 如果a为null则表示删除头节点bif (a &#61;&#61; null) {head &#61; head.next;} elsea.next &#61; b.next;}// 删除存储的数据值为value的节点public void remove(int value) {Node q &#61; head;Node p &#61; null;// 遍历整个单向链表&#xff0c;查询具体存放数据为value的节点while (q !&#61; null && q.data !&#61; value) {p &#61; q;q &#61; q.next;}if (q !&#61; null) {if (p &#61;&#61; null)head &#61; q.next;elsep.next &#61; q.next;}}

查找节点

// 查找存储数据为 value的节点public Node find(int value) {Node p &#61; head;while (p !&#61; null && p.data !&#61; value) {p &#61; p.next;}return p;}

获取指定下标的节点

// 获取指定下标的节点public Node get(int index) {Node p &#61; head;int res &#61; 0;while (p !&#61; null && res !&#61; index) {res&#43;&#43;;p &#61; p.next;}return p;}

Java集合

Java集合类存放于java.util包中&#xff0c;是用于存放对象的容器


  • 集合中只能存放对象&#xff0c;如果存入一个简单类型&#xff0c;实际上进行了自动转换【装箱】
  • 集合中存放的是多个对象的引用&#xff0c;对象本身还是存放在堆内存
  • 集合中可以存放不同类型、不限数量的数据

Collection接口

一般来说 Collection 接口是集合框架的顶级接口&#xff0c;但是事实上不是

特征&#xff1a; 集合中的数据无序&#xff0c;允许重复

接口中定义的方法&#xff1a;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rXNimSUO-1649138014449)(C:\Users\阿白\AppData\Roaming\Typora\typora-user-images\image-20220215220311721.png)]

size():int 获取集合中的元素个数


  • 数组中实际上是不能直接获取其中存储的元素个数&#xff0c;集合中可以分为两个概念&#xff1a;容器是表示可以存放的元素个数&#xff0c;类似于集合的 length&#xff1b;size 表示实际存储的元素个数

add(Object obj):boolean 向集合中添加元素 obj

isEmpty():boolean 判断集合中的元素个数是否为 0

​ 注意&#xff1a;只判断集合中是否没有元素&#xff0c;并不会判断集合是否为 null


  • cc.size()<1

contains(Object obj):boolean 判断当前集合中是否包含对象 obj


  • 使用&#61;&#61;还是 equals 进行判定&#xff1f; equals

Object 类中的 equals 方法定义

public boolean equals(Object obj){return (this &#61;&#61; obj);
}

如果自定义类中没有定义 equals 方法时&#xff0c;其中的 equals 方法是从 Object 类中继承得到的&#xff0c;这个方法是采用&#61;&#61;进行判断&#xff0c;如果需要按照某个业务规则进行判断&#xff0c;则必须自定义覆盖 equals 方法

toArray():Object[]将集合转换为数组

add(Object obj):boolean 向集合中添加元素 obj

addAll(Collection) 将另外一个集合中的所有元素添加到当前集合中

remove(Object obj):boolean 从集合中删除指定的元素 obj

clear():void 清空集合中的所有元素


List子接口

Collection 接口的子接口&#xff0c;特征&#xff1a;数据有序【索引编号】允许重复。在 Collection 接口的基础上添加了每个元素的索引编号&#xff0c;编号从 0 开始到 size-1 结束

public interface List<E> extends Collection<E>{}

add(Object):boolean 向集合末尾追加元素

add(int index, E element):void 向指定索引位置 index 上添加元素 element&#xff0c;原始数据自动后移

remove(Object):boolean 删除第一个和 object 参数相等的元素&#xff0c;实际上是 Collection 接口中的方法

remove(int index):Object 删除指定索引值对应的元素&#xff0c;并返回被删除的元素。

get(int index):E 获取指定索引号对应的元素&#xff0c;要求 index 应该在[0,size-1]范围内&#xff0c;否则异常

set(int index, E element):E 用于给指定索引位置上进行赋值操作&#xff0c;这个位置上必须有对应的数据&#xff0c;已经赋过值了&#xff0c;这里实际上就是修改操作&#xff0c;否则越界异常

indexOf(Object obj):int 从前向后查询第一个元素和 obj 相等的元素的对应索引值。如果不存在相等的时候返回-1

lastIndexOf(Object obj):int 从后向前查询最后一个元素和 obj 相等的元素的对应索引值。如果不存在相等的时候返回-1


Set子接口

没有新的方法&#xff0c;特征&#xff1a;无序、不允许重复

public interface Set<E> extends Collection<E>{}

基础用法

int index, E element):E 用于给指定索引位置上进行赋值操作&#xff0c;这个位置上必须有对应的数据&#xff0c;已经赋过值了&#xff0c;这里实际上就是修改操作&#xff0c;否则越界异常

indexOf(Object obj):int 从前向后查询第一个元素和 obj 相等的元素的对应索引值。如果不存在相等的时候返回-1

lastIndexOf(Object obj):int 从后向前查询最后一个元素和 obj 相等的元素的对应索引值。如果不存在相等的时候返回-1


Set子接口

没有新的方法&#xff0c;特征&#xff1a;无序、不允许重复

public interface Set<E> extends Collection<E>{}

基础用法
在这里插入图片描述


推荐阅读
  • 本文深入探讨了Java多线程环境下的同步机制及其应用,重点介绍了`synchronized`关键字的使用方法和原理。`synchronized`关键字主要用于确保多个线程在访问共享资源时的互斥性和原子性。通过具体示例,如在一个类中使用`synchronized`修饰方法,展示了如何实现线程安全的代码块。此外,文章还讨论了`ReentrantLock`等其他同步工具的优缺点,并提供了实际应用场景中的最佳实践。 ... [详细]
  • 深入解析CAS机制:全面替代传统锁的底层原理与应用
    本文深入探讨了CAS(Compare-and-Swap)机制,分析了其作为传统锁的替代方案在并发控制中的优势与原理。CAS通过原子操作确保数据的一致性,避免了传统锁带来的性能瓶颈和死锁问题。文章详细解析了CAS的工作机制,并结合实际应用场景,展示了其在高并发环境下的高效性和可靠性。 ... [详细]
  • 如何利用Java 5 Executor框架高效构建和管理线程池
    Java 5 引入了 Executor 框架,为开发人员提供了一种高效管理和构建线程池的方法。该框架通过将任务提交与任务执行分离,简化了多线程编程的复杂性。利用 Executor 框架,开发人员可以更灵活地控制线程的创建、分配和管理,从而提高服务器端应用的性能和响应能力。此外,该框架还提供了多种线程池实现,如固定线程池、缓存线程池和单线程池,以适应不同的应用场景和需求。 ... [详细]
  • Web开发框架概览:Java与JavaScript技术及框架综述
    Web开发涉及服务器端和客户端的协同工作。在服务器端,Java是一种优秀的编程语言,适用于构建各种功能模块,如通过Servlet实现特定服务。客户端则主要依赖HTML进行内容展示,同时借助JavaScript增强交互性和动态效果。此外,现代Web开发还广泛使用各种框架和库,如Spring Boot、React和Vue.js,以提高开发效率和应用性能。 ... [详细]
  • PHP预处理常量详解:如何定义与使用常量 ... [详细]
  • 在当前的软件开发领域,Lua 作为一种轻量级脚本语言,在 .NET 生态系统中的应用逐渐受到关注。本文探讨了 Lua 在 .NET 环境下的集成方法及其面临的挑战,包括性能优化、互操作性和生态支持等方面。尽管存在一定的技术障碍,但通过不断的学习和实践,开发者能够克服这些困难,拓展 Lua 在 .NET 中的应用场景。 ... [详细]
  • 手指触控|Android电容屏幕驱动调试指南
    手指触控|Android电容屏幕驱动调试指南 ... [详细]
  • AIX编程挑战赛:AIX正方形问题的算法解析与Java代码实现
    在昨晚的阅读中,我注意到了CSDN博主西部阿呆-小草屋发表的一篇文章《AIX程序设计大赛——AIX正方形问题》。该文详细阐述了AIX正方形问题的背景,并提供了一种基于Java语言的解决方案。本文将深入解析这一算法的核心思想,并展示具体的Java代码实现,旨在为参赛者和编程爱好者提供有价值的参考。 ... [详细]
  • R语言中向量(Vector)数据类型的元素索引与访问:利用中括号[]和赋值操作符在向量末尾追加数据以扩展其长度
    在R语言中,向量(Vector)数据类型的元素可以通过中括号 `[]` 进行索引和访问。此外,利用中括号和赋值操作符,可以在向量的末尾追加新数据,从而动态地扩展向量的长度。这种方法不仅简洁高效,还能灵活地管理向量中的数据。 ... [详细]
  • 深入解析Java虚拟机的内存分区与管理机制
    Java虚拟机的内存分区与管理机制复杂且精细。其中,某些内存区域在虚拟机启动时即创建并持续存在,而另一些则随用户线程的生命周期动态创建和销毁。例如,每个线程都拥有一个独立的程序计数器,确保线程切换后能够准确恢复到之前的执行位置。这种设计不仅提高了多线程环境下的执行效率,还增强了系统的稳定性和可靠性。 ... [详细]
  • V8不仅是一款著名的八缸发动机,广泛应用于道奇Charger、宾利Continental GT和BossHoss摩托车中。自2008年以来,作为Chromium项目的一部分,V8 JavaScript引擎在性能优化和技术创新方面取得了显著进展。该引擎通过先进的编译技术和高效的垃圾回收机制,显著提升了JavaScript的执行效率,为现代Web应用提供了强大的支持。持续的优化和创新使得V8在处理复杂计算和大规模数据时表现更加出色,成为众多开发者和企业的首选。 ... [详细]
  • 如何撰写适应变化的高效代码:策略与实践
    编写高质量且适应变化的代码是每位程序员的追求。优质代码的关键在于其可维护性和可扩展性。本文将从面向对象编程的角度出发,探讨实现这一目标的具体策略与实践方法,帮助开发者提升代码效率和灵活性。 ... [详细]
  • 线程能否先以安全方式获取对象,再进行非安全发布? ... [详细]
  • 开发日志:201521044091 《Java编程基础》第11周学习心得与总结
    开发日志:201521044091 《Java编程基础》第11周学习心得与总结 ... [详细]
  • JavaScript XML操作实用工具类:XmlUtilsJS技巧与应用 ... [详细]
author-avatar
企鹅田先生
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有