第一章 概述
www.leetcode-cn.com LeetCode中文网(数据结构与算法题)
www.newcoder.com 牛客网(面试真题)
集合构造→线性结构→树形结构→图形结构→
物理存储结构:
顺序存储结构(连续) 查找快,增删慢
链式存储结构(随机) 查找慢,增删快
数组和链表是实现方式
算法时间复杂度(考虑数量级,看变化趋势):算法的好坏由时间复杂度定义
常数阶O(1):无循环体,随N的增大,运行次数不变
线性阶O(n):忽略常数,忽略N的系数
对数阶O(logn):虽有循环,虽然也随N的增大而增大,
但这种增大属于加速度减小的加速运动
平方阶O(n^2):忽略常数,只保留幂高项,且忽略幂高项系数
比较:
O(1)
第二章 动态数组
java中内置数组的特点:
地址连续、提供角标、只能存同一类型的数据、数组长度一旦确定则不可更改
Java内置数组扩容:copyof
如何封装动态数组:
属性方面:int size 数组的有效元素个数
int capacity 数组的最大容量data.length
E[ ] data 数据的存储容器(E指泛型)
行为方面:增、删、改、查、其他
动态数组是顺序存储结构的具体实现
线性表:0个或多个数据元素的有限序列
public int getSize():
获取线性表的元素个数(线性表的长度),
@return 返回值是线性表中有效元素的个数
public boolean isEmpty():
判断线性表是否为空,
@return 返回值是布尔类型值
public void add(int index,E e):
在线性表中指定的index角标出添加元素e,
@param index指定的角标0<=index<=size,
@param e要插入的元素
public void addFirst(E e):
在线性表的表头位置插入一个元素,
@param e要插入的元素指定在角标0处
public void addLast(E e):
在线性表的末尾插入一个元素,
@param e要插入的元素 指定在角标size处
public E get(int index):
在线性表中获取指定index角标处的元素,
@param index 指定的角标 0<=index<size,
@return该角标所对应的元素
public E getFirst():
获取线性表中表头中元素,
@return 表头元素 index=0
public E getLast():
获取线性表中表尾的元素,
@return 表尾的元素 index=size-1
public void set(int index,E e):
修改线性表中指定index处的元素为新元素e,
@param index 指定的角标,
@param e 新元素
public boolean contains(E e):
判断线性表中是否包含自顶元素e 默认从前往后找,
@param e 要判断是否存在的元素,
@return 元素的存在性布尔类型值
public int find(E e):
在线性表中获取指定元素e的角标 默认从前往后,
@param e 要查询的数据,
@return 数据在线性表中的角标
public E remove(int index):
在线性表中删除指定角标处的元素 并返回,
@param index 指定的角标 0<=index<size,
@return 删除掉的老元素
public E removeFirst():
删除线性表中的表头元素,
@return 表头元素
public E removeLast():
删除线性表中的表尾元素,
@return 表尾元素
public void removeElement(E e):
在线性表中删除指定元素e
public void clear():
清空线性表
用顺序存储结构实现的List-顺序线性表-顺序表
public class ArrayList<E> implements List<E> {
private static int DEFAULT_SIZE=10; //容器的默认容量
private E[] data; //存储数据元素的容器
private int size; //线性表的有效元素的个数
//data.length表示线性表的最大容量Capacity
/**
* 创建一个容量默认为10的一个线性表
* */
public ArrayList(){
this(DEFAULT_SIZE);
}
/**
* 创建一个容量为指定capacity的一个线性表
* */
public ArrayList(int capacity){
this.data=(E[]) new Object[capacity];
this.size=0;
}
/**
* 将一个数组封装成为一个线性表
* */
public ArrayList(E[] arr){
data=(E[]) new Object[arr.length];
for(int i =0;i<data.length;i++){
data[i]=arr[i];
}
size=data.length;
}
add(int index, E e)方法的实现
public void add(int index, E e) {
if(index<0||index>size){
throw new ArrayIndexOutOfBoundsException("add函数角标越界");
}
//判断是否以满
if(size==data.length){
resize(2*data.length);
}
for(int i=size-1;i>=index;i--){
//插入的时候从最后一个元素进行整体向右移一位
data[i+1]=data[i];
}
data[index]=e;
size++;//元素个数加1
}
扩容
改变data的长度(扩容,缩容) ,@param 新数组的长度
private void resize(int newLen) {
E[ ] newData=(E[ ]) new Object[newLen]; //创建一个新数组
for(int i=0;i<size;i++){
newData[i]=data[i];
}
data=newData;
}
remove方法的实现
public E remove(int index) {
if(index<0||index>size-1){
throw new ArrayIndexOutOfBoundsException("remove函数角标越界");
}
E e=get(index);
for(int i=index+1;i<=size-1;i++){
data[i-1]=data[i];
}
size--;
//判断是否缩容
//1.最短不能缩过默认容量
//2.有效元素的个数小于等于容量的1/4
if(data.length>DEFAULT_SIZE&&size<=data.length/4){
resize(data.length/2);
}
return e;
}
toString()方法的重写:
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append("ArrayList: size="+size+",capacity="+data.length+"\n");
if(isEmpty()){
sb.append("[]");
}else{
sb.append('[');
for(int i=0;i<size;i++){
sb.append(data[i]);
if(i==size-1){
sb.append(']');
}else{
sb.append(',');
}
}
}
return sb.toString();
}
public int getCapacity(){
return data.length;
}
public void swap(int i,int j){
//i j 判断
E temp=data[i];
data[i]=data[j];
data[j]=temp;
}
equals()方法的重写:
public boolean equals(Object obj) {
if(obj==null){
return false;
}
if(obj==this){
return true;
}
if(obj instanceof ArrayList){
//属于ArrayList才开始比较
ArrayList l=(ArrayList) obj; //将传入的obj转换为ArrayList
if(getSize()==l.getSize()){
//长度需要相等
for(int i=0;i<getSize();i++){
//obj中元素自身每个元素循环比较
if(get(i)!=l.get(i)){
//若不相等跳出循环
return false;
}
}
return true;
}
}
return false;
}