Java学习(集合框架)

集合框架(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 = { 2, 21, 49, 17, 50, 1 };
		for (int i = 0; i < arr.length - 1; i++) {
			for (int j = 0; j < arr.length - 1 - i; j++) {
				if (arr[j] > arr[j + 1]) {
					int tmp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = tmp;
				}
			}
		}
		System.out.println(Arrays.toString(arr));
	}
快速排序

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

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

数据结构概述

基本数据结构3种:线性表、树、图

线性表

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

特征:除了头尾元素,每个元素有且只有一个直接前驱和一个直接后继;而头元素,没有直接前驱,尾元素没有直接后继

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

数组

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

特点:

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

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

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

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

单向链表
public class Node{
	private int date;//存储集体数据
	private Node next;//记录下一个节点的作用,尾节点指向null

}

创建2个节点的流程

Node node1 = new Node();
node1.setDate(123);//具体存储数据,next此时为null;所以node1是一个尾节点

Node node2 = new Node();
node2.setDate(456);
node1.setNext(node2);//使node1的下一个元素指针指向到node2对象
Link的实现
public class linkList{
    private Node head = null;//整个链表的头指针
    
    public static class Node{
        private int date;
        private Node next;
    }
}

新增数据

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

删除数据

// 删除已知前驱节点为a的节点b,b的前驱节点为a
	public void remove(Node a, Node b) {
		// 如果a为null则表示删除头节点b
		if (a == null) {
			head = head.next;
		} else
			a.next = b.next;
	}

// 删除存储的数据值为value的节点
	public void remove(int value) {
		Node q = head;
		Node p = null;
		// 遍历整个单向链表,查询具体存放数据为value的节点
		while (q != null && q.data != value) {
			p = q;
			q = q.next;
		}
		if (q != null) {
			if (p == null)
				head = q.next;
			else
				p.next = q.next;
		}
	}

查找节点

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

获取指定下标的节点

// 获取指定下标的节点
	public Node get(int index) {
		Node p = head;
		int res = 0;
		while (p != null && res != index) {
			res++;
			p = p.next;
		}
		return p;
	}
Java集合

Java集合类存放于java.util包中,是用于存放对象的容器

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

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

特征: 集合中的数据无序,允许重复

接口中定义的方法:

在这里插入图片描述

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

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

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

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

​ 注意:只判断集合中是否没有元素,并不会判断集合是否为 null

  • cc.size()<1

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

  • 使用==还是 equals 进行判定? equals

Object 类中的 equals 方法定义

public boolean equals(Object obj){
	return (this == obj);
}

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

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

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

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

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

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

List子接口

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

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

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

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

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

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

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

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

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

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

Set子接口

没有新的方法,特征:无序、不允许重复

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

基础用法

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

个位置上必须有对应的数据,已经赋过值了,这里实际上就是修改操作,否则越界异常

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

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

Set子接口

没有新的方法,特征:无序、不允许重复

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值