线性表:
* 栈
* 队列
* 数组
* 链表
一、栈
LIFO:后进先出
FILO:先进后出
实现代码:
package com.openlab.collection;
import java.util.Arrays;
public class Stack {
private Object[] data;
private int size;
private int capacity;
public Stack() {
// 默认创建一个10容量的栈
this.capacity = 10;
data = new Object[this.capacity];
}
public Stack(int capacity) {
this.capacity = capacity;
data = new Object[this.capacity];
}
//进栈一个元素
public void push(Object e){
// 先判断栈是否已经满了
if (this.isFull()) {
// 扩容
// 扩容的规则是原有容量的1.5倍
int length = this.capacity + (this.capacity >>> 1);
this.resize(length);
} else {
this.data[size++] = e;
}
}
// 判断是否存满
private boolean isFull() {
return this.capacity == this.size;
}
// 扩容或缩容容器的大小
private void resize(int len){
// Object[] arr = new Object[len];
// for (int i = 0; i < data.length; i++) {
// arr[i] = data[i];
// }
// this.data = arr;
// 上面的代码等价于下面的
this.data = Arrays.copyOf(this.data, len);
this.capacity = len;
}
// 判断栈是否为空
public boolean isEmpty(){
return this.size == 0;
}
// 出栈一个元素
public Object pop(){
if (this.isEmpty()) {
throw new RuntimeException("对不起,栈中已经没有元素了");
}
return this.data[--this.size];
}
// 查看栈顶元素
public Object peek(){
return this.data[this.size - 1];
}
// 获取栈中元素的个数
public int size(){
return this.size;
}
// 清空栈
public void clear(){
this.size = 0;
}
// 返回栈的字符串形式
public String toString(){
return Arrays.toString(Arrays.copyOf(this.data, this.size));
}
// 对比两个栈是否相等
@Override
public boolean equals(Object o) {
Stack s = (Stack) o;
if (this.size != s.size()) {
return false;
}
for (int i = 0; i < s.size() ; i++) {
if (data[i] != s.data[i]) {
return false;
}
}
return true;
}
}
二、队列
FIFO:先进先出
LILO:后进后出
实现:
方法1:和栈类似,只需改变出队代码
方法2:利用两个栈来实现队列
1:
package com.openlab.collection;
import java.util.Arrays;
public class Queue {
private Object[] data;
private int size;
private int capacity;
public Queue() {
// 默认创建一个10容量的队列
this.capacity = 10;
data = new Object[this.capacity];
}
public Queue(int capacity) {
this.capacity = capacity;
data = new Object[this.capacity];
}
//进队列一个元素
public void push(Object e){
// 先判断队列是否已经满了
if (this.isFull()) {
// 扩容
// 扩容的规则是原有容量的1.5倍
int length = this.capacity + (this.capacity >>> 1);
this.resize(length);
} else {
this.data[size++] = e;
}
}
// 判断是否存满
private boolean isFull() {
return this.capacity == this.size;
}
// 扩容或缩容容器的大小
private void resize(int len){
this.data = Arrays.copyOf(this.data, len);
this.capacity = len;
}
// 判断队列是否为空
public boolean isEmpty(){
return this.size == 0;
}
// 出队列一个元素
public Object pop(){
if (this.isEmpty()) {
throw new RuntimeException("对不起,队列中已经没有元素了");
}
this.size--;
Object temp = this.data[0];
System.arraycopy(data, 1, this.data, 0, data.length - 1);
return temp;
}
// 查看队列顶元素
public Object peek(){
return this.data[this.size - 1];
}
// 获取队列中元素的个数
public int size(){
return this.size;
}
// 清空队列
public void clear(){
this.size = 0;
}
// 返回队列的字符串形式
public String toString(){
return Arrays.toString(Arrays.copyOf(this.data, this.size));
}
// 对比两个队列是否相等
@Override
public boolean equals(Object o) {
Queue s = (Queue) o;
if (this.size != s.size()) {
return false;
}
for (int i = 0; i < s.size() ; i++) {
if (data[i] != s.data[i]) {
return false;
}
}
return true;
}
}
2:
package com.openlab.collection;
public class Queue2 {
private Stack stackA;
private Stack stackB;
public Queue2() {
stackA = new Stack();
stackB = new Stack();
}
// 进队一个元素
public void offer(Object e){
this.stackA.push(e);
}
// 出队一个元素
public Object poll(){
remove();
return stackB.pop();
}
private void remove() {
if (this.stackB.size() == 0) {
while (this.stackA.size() != 0) {
this.stackB.push(this.stackA.pop());
}
}
}
// 查看队首元素
public Object element(){
if (this.stackB.size() != 0) {
return this.stackB.peek();
} else {
remove();
}
return this.stackB.peek();
}
// 获取队列中元素的个数
public int size(){
remove();
return this.stackB.size();
}
// 判断队列是否为空
public boolean isEmpty(){
return this.stackB.size() == 0 && this.stackA.size() == 0;
}
// 清空队列
public void clear(){
this.stackA.clear();
this.stackB.clear();
}
// 返回队列的字符串形式
public String toString(){
return "展示B中的值";
}
public boolean equals(Object o) {
return true;
}
}
三、数组
数组是相同类型元素的集合,用一段连续的空间来存放数组的内容。
package com.openlab.collection;
import java.util.Arrays;
/**
* 动态数组
*
*/
public class ArrayList {
private Object[] objs;
private int size;
private int capacity;
public ArrayList() {
this.capacity = 10;
this.objs = new Object[this.capacity];
}
public ArrayList(int capacity) {
this.capacity = capacity;
this.objs = new Object[this.capacity];
}
public void add(Object obj) {
if (this.isFull()) {
// 扩容
this.grow();
}
this.objs[size++] = obj;
}
private void grow() {
// 1.5 倍
int newCapaCity = this.capacity + (this.capacity >>> 1);
System.out.println("扩容开始,容量由"+ this.capacity +"变为:"+ newCapaCity);
this.objs = Arrays.copyOf(this.objs, newCapaCity);
this.capacity = newCapaCity;
System.out.println("扩容成功");
}
private boolean isFull() {
return this.size == this.capacity;
}
public void add(int index, Object obj) {
if (this.isFull()) {
this.grow();
}
for (int i = size; i > index ; i--) {
this.objs[i] = this.objs[i - 1];
}
this.objs[index] = obj;
this.size++;
}
public void remove(int index) {
for (int i = index; i < this.size - 1; i++) {
this.objs[index] = this.objs[index+1];
}
this.size--;
}
public void update(int index, Object obj) {
this.objs[index] = obj;
}
public Object load(Object Object) {
return null;
}
public Object get(int index) {
if (index < size) {
return null;
}
return this.objs[index];
}
public Object[] list() {
return Arrays.copyOf(this.objs, size);
}
public void clear() {
this.size = 0;
}
public String toString() {
return "ObjectMangerImpl [objs=" + Arrays.toString(objs) + ", size=" + size + ", capacity=" + capacity + "]";
}
public int size() {
return this.size;
}
}
四、 链表
双向循环链表:
package p3.链式结构;
import p1.接口.Dequeue;
import p1.接口.List;
import p1.接口.Stack;
import java.util.Comparator;
import java.util.Iterator;
//双向循环链表
public class LinkedList<E> implements List<E>, Dequeue<E>, Stack<E> {
private class Node {
E data;
Node pre;//直接前驱
Node next;//直接后继
public Node() {
this(null, null, null);
}
public Node(E data) {
this(data, null, null);
}
public Node(E data, Node pre, Node next) {
this.data = data;
this.pre = pre;
this.next = next;
}
@Override
public String toString() {
return data.toString();
}
}
private Node head;
private Node tail;
private int size;
public LinkedList() {
head = null;
tail = null;
size = 0;
}
public LinkedList(E[] arr) {
if (arr == null) {
throw new IllegalArgumentException("arr can not be null");
}
for (E e : arr) {
add(e);//默认在表尾添加
}
}
@Override
public void add(E element) {
add(size, element);
}
@Override
public void add(int index, E element) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("add index out of range");
}
Node n = new Node(element);
if (size == 0) {//刚开始链表为空的,来个新节点对象,直接head ,tail 指向新节点
head = n;
tail = n;
tail.next = head;//节点的下一跳 尾的下一跳指头 体现循环
head.pre = tail;//节点的上一跳(前驱) 头的下一跳应该是尾
} else if (index == 0) {//要插入的角标在第一个
//先把当前(头)上一跳给 新节点的上一跳(指的尾) 新节点的下一跳指向当前的head 当前头的上一跳指新节点 head更新为新节点 尾的下一跳更新为当前的head
n.pre = head.pre;
n.next = head;
head.pre = n;
head = n;
tail.next = head;
} else if (index == size) {//在表尾
//从右向左读 :先把当前尾的下一跳给新节点的下一跳(或者说从左向右读 新节点的下一跳指向尾的下一跳) 尾的下一跳指向新节点 新节点的上一跳指向当前尾 尾更新为新节点 头的上一跳重新指向尾
n.next = tail.next;
n.pre = tail;
tail.next = n;
tail = n;
head.pre = tail;
} else {//中间
Node p, q;//要插入节点位置的前驱 后继(也是要插入的位置) p q
if (index <= size / 2) {//链表偏左的地方添加
p = head;
for (int i = 0; i < index - 1; i++) {//如在i=2位置添加元素 需要找到其前驱,i=0 i<2-1=1 0-1 移动一次 刚好到i=1的位置 即为 i=2的前驱
p = p.next;
}
q = p.next;
// p的下一跳指向新节点 新节点的上一跳指向p q的上一跳指向新节点 新节点的下一跳指向q
p.next = n;
n.pre = p;
q.pre = n;
n.next = q;
} else {//链表偏右的地方添加
p = tail;//从尾部找起 此时q是p的前驱
for (int i = size - 1; i > index; i--) {//如在index=4的位置添加元素 size=6 i=size-1=5,i>index 移一个 i--=4 4
p = p.pre;
}
q = p.pre;
//q的下一跳指向新节点 新节点的上一跳指向q p的上一跳指向新节点 新节点的下一跳指向p
q.next = n;
n.pre = q;
n.next = p;
p.pre = n;
}
}
size++;
}
@Override
public void remove(E element) {
int index = indexof(element);
if (index != -1) {//!=-1 即存在 根据角标删除即可
remove(index);
}
}
@Override
public E remove(int index) {
if (index < 0 || index > size) {
throw new IllegalArgumentException("remove index out of range");
}
E ret = null;
Node node;
if (size == 1) {
ret = head.data;
head = null;
tail = null;
} else if (index == 0) {
ret = head.data;//保存值
node = head.next;//node作辅助用 找到新的头节点
head.next = null;//先断head和node的联系
node.pre = head.pre;//head的上一跳给node的上一跳
head.pre = null;//head的上一跳还存在 指向着尾 将它清空,不再指向任何
head = node;//head重新指向node
tail.next = head;//尾的下一跳指向头
} else if (index == size - 1) {
ret = tail.data;
node = tail.pre;//先找到新的尾节点 node
tail.pre = null;//tail上一跳置空
node.next = tail.next;//tail的下一跳给node的下一跳(让node指向头)
tail.next = null;//tail下一跳置空
tail = node;//tail指向新的尾节点
head.pre = tail;//头的上一跳重新更新为当前的尾节点
} else {
Node p, q, r;//要删除节点的前驱 要删除节点 要删除节点的后继
if (index <= size / 2) {
p = head;
for (int i = 0; i < index - 1; i++) {
p = p.next;
}
q = p.next;
r = q.next;
ret = q.data;
p.next = r;//p的下一跳指向r
r.pre = p;//r的上一跳指向p
q.next = null;//q上下置空
q.pre = null;
} else {
p = tail;
for (int i = size - 1; i > index + 1; i++) {//如在index=4的位置删除元素 i=size-1=6 i>index+1=5 移一个 i++=6 不移
p = p.pre;
}
q = p.pre;
r = q.pre;
ret = q.data;
r.next = p;
p.pre = r;
q.next = null;
q.pre = null;
}
}
size--;
return ret;
}
@Override
public E get(int index) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("get index out of range");
}
if (index == 0) {
return head.data;
} else if (index == size - 1) {
return tail.data;
} else {
Node p = head;
for (int i = 0; i < index; i++) {
p = p.next;
}
return p.data;
}
}
@Override
public E set(int index, E element) {
if (index < 0 || index >= size) {
throw new IllegalArgumentException("get index out of range");
}
E ret = null;
if (index == 0) {
ret = head.data;
head.data = element;
} else if (index == size - 1) {
ret = tail.data;
tail.data = element;
} else {
Node p = head;
for (int i = 0; i < index; i++) {
p = p.next;
}
ret = p.data;
p.data = element;
}
return ret;
}
@Override
public int size() {
return size;
}
@Override
public int indexof(E element) {
Node p = head;
int index = 0;
while (!p.data.equals(element)) {
p = p.next;
index++;
if (p == head) {
return -1;
}
}
return index;
}
@Override
public boolean contains(E element) {
return indexof(element) != 0;
}
@Override
public boolean isEmpty() {
return size == 0 && head == null && tail == null;
}
@Override
public void clear() {
head = null;
tail = null;
size = 0;
}
@Override
public void sort(Comparator<E> c) {
if (c == null) {
throw new IllegalArgumentException("comparator can not be null");
}
if (size == 0 || size == 1) {
return;
}
//插入排序来做
for (Node nodeA = head.next; nodeA != head; nodeA = nodeA.next) {
E e = nodeA.data;
Node nodeB;
Node nodeC;
for (nodeB = nodeA, nodeC = nodeB.pre; nodeC != tail && c.compare(nodeC.data, e) > 0; nodeB = nodeB.pre, nodeC = nodeC.pre) {//或者判断的条件为nodeB!=head 都表示结束
nodeB.data = nodeC.data;
}
nodeB.data = e;
}
}
@Override
public List<E> sublist(int fromIndex, int toIndex) {
if (fromIndex < 0 || toIndex >= size || fromIndex > toIndex) {
throw new IllegalArgumentException("0<=fromIndex<=toIndex<size");
}
Node nodeA = head;
for (int i = 0; i < fromIndex; i++) {
nodeA = nodeA.next;
}
Node nodeB = head;
for (int i = 0; i < toIndex; i++) {
nodeB = nodeB.next;
}
Node p = nodeA;
LinkedList<E> list = new LinkedList<>();
while (true) {//从A开始移,先放再移 ,直到B
list.add(p.data);//到B时,先把nodeB加进去,判断是NodeB就跳出
if (p == nodeB) {
break;
}
p = p.next;
}
return list;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
if (isEmpty()) {
sb.append(']');
} else {
Node p = head;
while (true) {
sb.append(p.data);
if (p == tail) {
sb.append(']');
break;
} else {
sb.append(',');
sb.append(' ');
p = p.next;
}
}
}
return sb.toString();
}
@Override
public Iterator<E> iterator() {
return new LinkedListIterator();
}
class LinkedListIterator implements Iterator<E> {
private Node cur = head;
private boolean flag = true;//是否在第一圈
@Override
public boolean hasNext() {
if (isEmpty()) {
return false;
}
return flag;
}
@Override
public E next() {
E ret = cur.data;
cur = cur.next;
if (cur == head) {
flag = false;
}
return ret;
}
}
//双端队列的方法
@Override
public void addFirst(E element) {
add(0, element);
}
@Override
public void addLast(E element) {
add(size, element);
}
@Override
public E removeFirst() {
return remove(0);
}
@Override
public E removeLast() {
return remove(size-1);
}
@Override
public E getFirst() {
return get(0);
}
@Override
public E getLast() {
return get(size-1);
}
//栈的方法
@Override
public void push(E element) {
addLast(element);
}
@Override
public E pop() {
return removeLast();
}
@Override
public E peek() {
return getLast();
}
//队列的方法
@Override
public void offer(E element) {
addLast(element);
}
@Override
public E poll() {
return removeFirst();
}
@Override
public E element() {
return getFirst();
}
}