文章目录
前言
程序 = 数据结构 + 算法,数据结构在问题解决中主要用来存放要处理的数据与实现算法策略。
一、基础概念
1.1 数据结构的概念
数据结构是计算机存储,组织数据的一种方式。
1.2 常见的数据结构
- 线性结构线性表(数组,链表,栈,队列,哈希表)
- 树形结构(二叉树,AVL树,红黑树,B树,哈夫曼树,堆)
- 图形结构(邻接矩阵,邻接表)
1.3 数据结构与算法的关系
个人总结:采用合适的数据结构为优秀的算法提供前提,优秀的算法是合适的数据结构的体现。
二、线性表
2.1 线性表定义
1.线性表:由N(N>=0)个相同数据类型的元素组成的有限序列,其中除了第一个数据元素没有前驱节点外,每个元素有且仅有一个直接的前驱节点,除最后一个数据元素外,每个数据元素都有且仅有一个直接后继节点。
2.2 常见的线性表
常见的线性表有:数组,链表,栈,队列,哈希表(散列表),本专栏会一一介绍。
2.3 数组
2.3.2 数组是一种顺序存储的线性表,所有元素的逻辑上连续,内存地址也连续。
2.4 顺序表的优缺点
- 优点:
1.存取速度高效,可以通过下标直接访问。 - 缺点:
1.存储空间是连续的,灵活性差,一旦声明就分配了初始容量存入的数据量少造成空间的浪费,存入的数据量大造成数组下标越界问题,事先难以确定数组长度。
2.插入删除操作涉及到数据元素的移动问题,效率低。
2.5 动态数组接口设计
针对以上顺序表的缺点,我们可以设计动态数组接口以解决顺序表的痛点,接口如下图所示:
2.6 泛型
若无泛型ArrayList只能存放单一的数据类型,使用泛型技术后可以让动态数组更加灵活与通用,可以存放任何数据类型。
public class ArrayList<E> {
private int size;
private E[] elements;
}
elements = (E[]) new Object[capacity];
ArrayList<Integer> list = new ArrayList<>();
2.7 代码实现
/**
* 动态数组的设计
* @Author huang.bX
* @Date 2021/7/21
*/
public class ArrayList<E> {
/**
* 数组中元素个数
*/
private int size;
/**
* 定义elements数组
*/
private E[] elements;
//默认初始化常量
private static final int DEFAULT_CAPACITY = 10;
//默认无元素常量
private static final int ELEMENT_NOT_FOUND = -1;
public ArrayList(int initialCapacity){
if (initialCapacity < 0){
throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
}
initialCapacity = Math.max(initialCapacity, DEFAULT_CAPACITY);
elements = (E[]) new Object[initialCapacity];
}
public ArrayList(){
this(DEFAULT_CAPACITY);
}
/**
* 保证要有capacity的容量
*/
private void ensureCapacity(int capacity){
int oldCapacity = elements.length;
if (oldCapacity >= capacity) {
return;
}
//扩容容量为旧数组的的1.5倍
int newCapacity = oldCapacity + (oldCapacity >> 1);
E[] newElements = (E[]) new Object[newCapacity];
for (int i = 0; i < size; i++){
newElements[i] = elements[i];
}
elements = newElements;
System.out.println(oldCapacity+"扩容为:"+newCapacity);
}
/**
*获取集合中的数据元素的个数
*/
public int size(){
return size;
}
/**
*判断集合是否为空(无数据元素)
*/
public boolean isEmpty() {
return size == 0;
}
/**
*获取集合中数据元素是否包含element参数
*/
public boolean contains(E element){
return indexOf(element) != ELEMENT_NOT_FOUND;
}
/**
*向集合中添加数据元素
*/
public void add(E element){
/*
elements[size] = element;
size++;
*/
add(size, element);
}
/**
*向集合中获取指定位置的数据元素
*/
public E get(int index){
rangeCheck(index);
return elements[index];
}
/**
设置index位置的元素
*/
public E set(int index, E element){
rangeCheck(index);
E old = elements[index];
elements[index] = element;
return old;
}
private void outOfBounds(int index){
throw new IndexOutOfBoundsException("Index:" + index+ ",Size:" +size);
}
private void rangeCheck(int index){
if (index < 0 || index >= size){
outOfBounds(index);
}
}
private void rangeCheckForAdd(int index){
if (index < 0 || index > size){
outOfBounds(index);
}
}
/**
*向集合中指定位置添加数据元素
*/
public void add(int index, E element){
rangeCheckForAdd(index);
ensureCapacity(size + 1);
for (int i = size -1; i >= index; i--){
elements[i+1] = elements[i];
}
elements[index] = element;
size++;
}
/**
*删除index位置对应的数据元素
*/
public E remove(int index){
if (isEmpty()){
throw new RuntimeException("集合中的数据元素为空,删除元素失败!");
}
rangeCheck(index);
for(int i = index; i < size - 1; i++){
elements[i] = elements[i+1];
}
size--;
elements[size] = null;
return elements[index];
}
/**
*查看数据元素的索引
* 判断传入的数据元素为null时的处理
* 不为空的数据元素.equals() 不然为空的数据元素中在前面会报空指针异常
*/
public int indexOf(E element){
if (element == null){
for (int i = 0; i < size; i++){
if(element == (elements[i])){
return i;
}
}
}else{
for (int i = 0; i < size; i++){
if(element.equals(elements[i])){
return i;
}
}
}
return ELEMENT_NOT_FOUND;
}
/**
* 清除所有数据元素
*/
public void clear(){
/*
* 如果数组中存放的是引用数据类型,清空数据则只需要把每个数组对应的引用链断开
* 表明他是垃圾对象会被gc
* 重复使用的留下来,没用的就销毁(gc)
*/
for (int i = 0; i < size; i++){
elements[i] = null;
}
size = 0;
}
@Override
public String toString() {
StringBuilder string = new StringBuilder();
string.append("size=").append(size).append(", [");
for (int i = 0; i < size; i++){
if (i != 0){
string.append(", ");
}
string.append(elements[i]);
}
string.append("]");
return string.toString();
}
}
测试:
/**
* @Author huang.bingXian
* @Date 2021/7/21
*/
public class ArrayListTest {
public static void main(String[] args) {
//创建ArrayList对象往集合中添加元素
ArrayList<Integer> list = new ArrayList<>();
for (int i = 0; i < 30; i++){
list.add(i);
}
list.set(2, 80);
list.set(3, 90);
list.set(4, 100);
list.set(5, 101);
System.out.println("数组是否为空:" + list.isEmpty());
System.out.println("删除的元素为:" + list.remove(12));
System.out.println("索引的元素为:" + list.indexOf(4));
list.add(list.size(), 90);
System.out.println(list.get(4));
System.out.println(list);
// ArrayList<Person> arrayList = new ArrayList<>();
// arrayList.add(new Person(11,"罗斯"));
// arrayList.add(new Person(12,"杰克"));
// arrayList.add(new Person(13,"科比"));
// arrayList.add(new Person(14,"詹姆斯"));
// arrayList.add(null);
//
// System.out.println(arrayList.size());
//
arrayList.clear();
System.gc();
// System.out.println(arrayList);
}
}
运行结果:
自己设计一个类型,往集合中存储
/**
* @Author huang.bX
* @Date 2021/7/21
*/
@Data
public class Person {
private int id;
private String name;
public Person(int id,String name) {
this.id = id;
this.name = name;
}
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("person finalize!");
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (o instanceof Person){
Person arrayListPerson = (Person) o;
return this.id == arrayListPerson.id;
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(id, name);
}
}
运行测试注释掉的代码结果: