线性表定义
由零个或多个数据元素组成的有限序列。若元素存在多个,则第一个元素无前驱,最后一个无后继,其他元素都有且只有一个前驱和后继。线性表有两种物理存储结构:顺序存储结构和链式存储结构(顺序表和链表)。
线性表的顺序存储结构(顺序表)
线性表的顺序存储结构指的是用一段地址连续的存储单元依次存储线性表的数据元素。
物理上的存储方式事实上就是内存中找个初始地址,然后通过占位的形式,把一定的内存空间给占了,然后把相同数据类型的数据元素依次放在这块空地中。
顺序表定义
public class ArrayList {
private static final int MINIMUM_SIZE = 1024;
private Object[] array = new Object[MINIMUM_SIZE];
private int size;
}
对顺序表的操作
**********添加元素**********
public class ArrayList<T> {
//定义数组
private static final int MINIMUM_SIZE = 10;
private static Object[] array = new Object[MINIMUM_SIZE];
//定义元素个数
private int size;
/**
* 添加元素到表中(不指定位置)
* @return
*/
public boolean add(int value) {
array[size++] = value;
return true;
}
/**
* 添加元素到指定位置
* @param index //位置
* @param value //值
* @return
*/
public boolean add(int index,Object value) {
if(size >= array.length) {//元素的个数多于数组长度
array = Arrays.copyOf(array, size+(size<<1));//数组增长1.5倍
}if(size == index) {
array[size] = value;
}else {
System.arraycopy(array, index, array, index+1, size-index);//元素添加后元素后面的要都往后移一位
array[index] = value;
}
size++;//添加元素后元素个数+1
return true;
}
//测试
public static void main(String[] args) {
ArrayList<T> arr = new ArrayList<>();
arr.add(3);
for(Object s:array) {
System.out.println(s);
}
}
}
***************删除元素***************
public boolean remove(T value) {
for (int i=0;i<size;i++) {
if(value.equals(array[i])) {
remove(i);
return true;
}
}
return false;
}
public void remove(int index) {
if(index != --size) {
System.arraycopy(array, index+1, array, index, size-index);//注意这里是将要删掉的元素覆盖
}
array[size] = null;
}
***********set/get方法***********
public T set(int index, T value) {
if (index<0 || index>=size) return null;
T t = array[index];
array[index] = value;
return t;
}
public T get(int index) {
if (index<0 || index>=size) return null;
return array[index];
}
线性表的链式存储结构
链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间。
单链表
它包含两个域,一个信息域和一个指针域。这个链接指向列表中的下一个节点,而最后一个节点则指向一个空值。
一个单向链表的节点被分成两个部分。第一个部分保存或者显示关于节点的信息,第二个部分存储下一个节点的地址。单向链表只可向一个方向遍历。
单链表的定义
public class SinglyLinkedList<T> {
private static class Node<T>{
private T value = null; //数据域
private Node<T> next = null; //指针域
}
private int size = 0; //结点个数
private Node<T> head = null; //定义头结点
private Node<T> tail = null; //定义尾结点
}
单链表增删改查
public class SinglyLinkedList<T> {
/**
* 创建结点类
*
* @author wz
* @param <T>
*/
private static class Node<T> {
private T value = null; // 数据域
private Node<T> next = null; // 指针域(返回指向下一个Node的引用)
public Node(T value) {
this.value = value;
}
}
/**
* 单链表类属性
*/
private static int size = 0; // 结点个数
private Node<T> head = null; // 定义头结点
private Node<T> tail = null; // 定义尾结点
/**
* 添加元素方法(尾插入)
*
* @param value
*/
public void add(T value) {
if (head == null) {
head = new Node<T>(value);
tail = head;
return;
}
tail.next = new Node<T>(value);
tail = tail.next;
size++;
}
/**
* 头插入
*
* @param value
*/
public void insertBeforeHead(T value) {
if (head == null) {
head = new Node<T>(value);
tail = head;
} else {
Node<T> node = new Node<T>(value);
node.next = head;
head = node;
}
size++;
}
/**
* 指定位置前增加
*
* @param value
* @param index
*/
public void insert(int index, T value) {
if (index >= size || tail == null)
add(value);
else if (index <= 0 || head == null)
insertBeforeHead(value);
else {
Node<T> cur = head;
int i = 0;
while (i++ < index - 1) { //在指定位置后增加则将index-1改为index
cur = cur.next;
System.out.println("cao");
}
Node<T> temp = new Node<T>(value);
temp.next = cur.next;
cur.next = temp;
size++;
}
}
/**
* 遍历
*/
public String toString() {
StringBuilder sb = new StringBuilder();
Node<T> node = head;
while (node != null) {
sb.append(node.value).append(",");
node = node.next;
}
return sb.toString();
}
/**
* 根据index删除元素,利用while找出index所指的结点
* @param index
*/
public void delete(int index) {
if(index>=size) return ;
if(index<0) return ;
if(index==0) {
head = head.next;
size--;
if(size<=1) tail = head;
return ;
}
int i = 0;
Node<T> cur = head;
while(i++<index-1) {
cur = cur.next;
}
Node<T> temp = cur.next;
if(temp == tail) tail = cur;
cur.next = temp.next;
size--;
}
/**
* 根据元素删除链表中的元素
* @param obj
*/
public void delete(T obj) {
if(head == null) return ;
if(head.value == obj) {delete(0); return ;}
Node<T> pre = head,cur = head.next;
while(cur.value != obj) {
pre = cur;
cur = cur.next;
}
if(cur != null) {
if(cur == tail) tail = pre;
pre.next = cur.next;
size--;
}
}
public static void main(String[] args) {
SinglyLinkedList linkedlist = new SinglyLinkedList();
linkedlist.add("a1");
linkedlist.add("a2");
linkedlist.add("a3");
System.out.println(size);
linkedlist.insert(1, "haha");
System.out.println(linkedlist.toString());
}
}
双向链表
Java类库中LinkedList就是由双向链表构成的,详情请到 LinkedList源码解析。