一、数据结构
1、数据结构是一门基础学科
2、研究的是数据如何在计算机中进行组织和存储,使得我们可以高效的获取数据和修改数据
3、数据结构可以分为三类:
线性结构:数组、队列、栈、链表、哈希表……
树型结构:二叉树、二分搜索树、AVL树、红黑树、堆、Trie、线段树、并查集……
图结构:邻接矩阵、邻接表
排序算法
4、为什么学习数据结构
根据不同的应用,灵活的选择最合适的数据结构
数据结构 + 算法 = 程序
5、开发环境
IDEA,JDK8+
二、数组
1、数组基础
<1> 用来存储一组类型相同的数据
<2>在内存中,分配连续的空间,数组创建时要指定容量(大小)
<3>数据类型[ ] 数组名 int[ ] arr = new int[10]
<4>索引 -- 访问数组时通过索引进行操作
<5>索引从0开始,最大为arr.length - 1
<6>常见的数组:字符串,对象数组,哈希表
<7>常见的错误: NullPointException ArrayIndexOutOfBoundsException
2、演示数组的使用
3、使用数组时,最重要的就是数组的索引,通过索引可以对数组进行改和查操作
数组最大的优点:快速查询
数组最好应用于索引有语义的情况。
三、实例
基于java中的数组,进行二次封装,可以制作出我们自己的数组(可变数组)
package com.algo.lesson01;
/*
基于Java中的数组进行二次封装 制作一个可变数组
*/
// 泛型:就是类型作为参数
public class MyArr<T> {
private T[] data;//用来保存数据
private int size;//数组中实际存放元素的个数
private int capacity;//容量
public MyArr(int capacity) {
if (capacity <= 0) {
this.capacity = 10;
} else {
this.capacity = capacity;
}
this.size = 0;
this.data = (T[]) new Object[this.capacity];
}
//获取数组中实际存放元素的个数
public int getSize() {
return this.size;
}
//获取数组的容积
public int getCapacity() {
return this.capacity;
}
//判断数组是否为空
public boolean isEmpty() {
return this.size == 0;
}
//向数组中添加元素(在尾部)
public void add(T item) {
//this.size 指向的是待插入元素的位置
addInIndex(this.size, item);
}
// 向数组中添加元素(在头部添加)
public void addHead(T item) {
addInIndex(0, item);
}
//根据索引修改值
public void setValueByIndex(int index, T val) {
if (index < 0 || index >= this.size) {
throw new IllegalArgumentException("index is invalid");
}
this.data[size] = val;
}
//向数组中指定位置添加元素
public void addInIndex(int index, T val) {
if (index < 0 || index > this.size) {
throw new IllegalArgumentException("index is invalid");
}
// 判断数组是否满
if (this.size == this.capacity) {
//扩容
resize(this.capacity * 2);
}
//从index 位置开始元素需要进行后移
for (int i = this.size - 1; i >= index; i--) {
this.data[i + 1] = this.data[i];
}
this.data[index] = val;
//更新 this.size
this.size++;
}
private void resize(int newCapacity) {
T[] newData = (T[]) (new Object[newCapacity]);
//将原数组中元素加入到新数组
for (int i = 0; i < this.size; i++) {
newData[i] = this.data[i];
}
//改变容器与容积
this.data = newData;
this.capacity = newCapacity;
}
//修改指定位置的值
public void modifyValueByIndex(int index, T value) {
//入参一定要判断
if (index < 0 || index >= this.capacity) {
throw new IllegalArgumentException("index is invalid");
}
this.data[index] = value;
}
//获取指定索引位置的值
public T getValueByIndex(int index) {
//入参一定要判断
if (index < 0 || index >= this.capacity) {
throw new IllegalArgumentException("index is invalid");
}
return this.data[index];
}
//查询指定的值在数组中是否存在,如果存在 获取索引 否则返回-1
public int containsValue(T val) {
//遍历数组
for (int i = 0; i < this.size; i++) {
if (val.equals(this.data[i])) {
return i;
}
}
return -1;
}
//根据索引删除从数组中删除元素
public T removeByIndex(int index) {
if (index < 0 || index >= this.capacity) {
throw new IllegalArgumentException("index is invalid");
}
//删除操作的核心
/*
1、找到删除的位置
2、删除位置之后的元素要前移 arr[i-1]=arr[j]
*/
T delValue = this.data[index];
for (int i = index + 1; i < this.size; i++) {
this.data[i - 1] = this.data[i];
}
this.size--;
//判断是否缩容
if (this.size <= this.capacity / 4 && this.capacity / 2 > 0) {
resize(this.capacity / 2);
}
return delValue;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
for (int i = 0; i < this.size; i++) {
sb.append(this.data[i]);
if (i != this.size - 1) {
sb.append(",");
}
}
sb.append("]");
return sb.toString();
}
/*
* 1、如果向数组中继续添加一个元素,就会出错(解决办法:扩容)
* 2、现在只能处理int类型,如何处理多种类型--(解决办法:泛型)
* 3、删除元素后,空间利用率低 --(解决办法:缩容)
* */
}