目录
1动态数组
1.1双端栈
1.1.1双端栈的定义
是指将一个线性表的两端当做栈底分别进行入栈和出栈操作 主要利用了栈“栈底位置不变,而栈顶位置动态变化” 的特性。
1.1.2ArrayDoubleEndStack类
package P2.线性结构; import java.util.Iterator; //双端栈 public class ArrayDoubleEndStack<E> implements Iterable<E> { //左端栈的栈顶 private int ltop; //右端栈的栈顶 private int rtop; //存储元素的容器 private E[] data; //数组容器的默认容量 private static int DEFAULT_CAPACITY = 10; public ArrayDoubleEndStack() { data = (E[]) new Object[DEFAULT_CAPACITY]; ltop = -1; rtop = data.length; } public void pushLeft(E element) { if (ltop + 1 == rtop) { resize(data.length * 2); } data[++ltop] = element; } public void pushRight(E element) { if (ltop + 1 == rtop) { resize(data.length * 2); } data[--rtop] = element; } private void resize(int newLen) { E[] newData = (E[]) new Object[newLen]; //复制左端栈的元素 for (int i = 0; i <= ltop; i++) { newData[i] = data[i]; } //复制右端栈的元素 int index = rtop; for (int i = newLen - sizeRight(); i < newLen; i++) { newData[i] = data[index++]; } rtop = newLen - sizeRight(); data = newData; } public E popLeft() { if (isLeftEmpty()) { throw new IllegalArgumentException("left stack is null"); } E ret = data[ltop--]; if (sizeLeft() + sizeRight() <= data.length / 4 && data.length > DEFAULT_CAPACITY) { resize(data.length / 2); } return ret; } public E popRight() { if (isRightEmpty()) { throw new IllegalArgumentException("right stack is null"); } E ret = data[rtop++]; if (sizeLeft() + sizeRight() <= data.length / 4 && data.length > DEFAULT_CAPACITY) { resize(data.length / 2); } return ret; } public E peekLeft() { if (isLeftEmpty()) { throw new IllegalArgumentException("left stack is null"); } return data[ltop]; } public E peekRight() { if (isRightEmpty()) { throw new IllegalArgumentException("right stack is null"); } return data[rtop]; } public boolean isLeftEmpty() { return ltop == -1; } public boolean isRightEmpty() { return rtop == data.length; } public int sizeLeft() { return ltop + 1; } public int sizeRight() { return data.length - rtop; } @Override public String toString() { // 1 2 3 7 8 9 StringBuilder sb = new StringBuilder(); sb.append('['); if (isLeftEmpty() && isRightEmpty()) { sb.append(']'); return sb.toString(); } //先搞左边 for (int i = 0; i <= ltop; i++) { sb.append(data[i]); if (i == ltop && isRightEmpty()) { sb.append(']'); return sb.toString(); } else { sb.append(','); } } //后搞右边 for (int i = rtop; i < data.length; i++) { sb.append(data[i]); if (i == data.length - 1) { sb.append(']'); } else { sb.append(','); } } return sb.toString(); } @Override public Iterator<E> iterator() { return new ArrayDoubleEndStackIterator(); } class ArrayDoubleEndStackIterator implements Iterator<E> { private ArrayList<E> list; private Iterator<E> it; public ArrayDoubleEndStackIterator() { list = new ArrayList<>(); for (int i = 0; i <= ltop; i++) { list.add(data[i]); } for (int i = rtop; i < data.length; i++) { list.add(data[i]); } it = list.iterator(); } @Override public boolean hasNext() { return it.hasNext(); } @Override public E next() { return it.next(); } } }
1.2队列
1.2.1队列的定义
队列是只允许在一端进行插入操作,而在另一端进行删除操作的线性表 我们把允许删除的一端称为队首(front),插入的一端称为队尾(rear) 不含任何数据元素的队列称为空队列 队列是一种先进先出(First In Last Out)的线性表,简称FIFO 队列本身是一个线性表,其数据元素具有线性关系,只不过它是一种特殊的线性表而已 队列的插入操作,叫作入队 队列的删除操作,叫作出队
1.2.2Queue队列接口的定义
package P1.接口; public interface Queue<E> extends Iterable<E> { public void offer(E element); //入队 public E poll(); //出队 public E peek(); //查看队首元素 public boolean isEmpty(); public void clear(); public int size(); }
1.2.3 ArrayQueue类
package P2.线性结构;
import P1.接口.Queue;
import java.util.Iterator;
public class ArrayQueue<E> implements Queue<E> {
private ArrayList<E> list;
public ArrayQueue() {
list = new ArrayList<>();
}
@Override
public void offer(E element) {
list.add(list.size(), element);
}
@Override
public E poll() {
return list.remove(0);
}
@Override
public E peek() {
return list.get(0);
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void clear() {
list.clear();
}
@Override
public int size() {
return list.size();
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public String toString() {
return list.toString();
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (this == o) {
return true;
}
if (o instanceof ArrayQueue) {
ArrayQueue other = (ArrayQueue) o;
return list.equals(other.list);
}
return false;
}
}
1.3队列实现栈
1.3.1QueTostack类
package P2.线性结构;
import P1.接口.Stack;
import java.util.Iterator;
public class QueueToStack {
public static void main(String[] args) {
StackImplByQueue<Integer> stack = new StackImplByQueue<>();
System.out.println(stack);
for (int i = 1; i <= 5; i++) {
stack.push(i); //队列A
}
System.out.println(stack.toString());
System.out.println(stack.pop());
System.out.println(stack); //队列B
}
}
class StackImplByQueue<E> implements Stack<E> {
private ArrayQueue<E> queueA;
private ArrayQueue<E> queueB;
public StackImplByQueue() {
queueA = new ArrayQueue<>();
queueB = new ArrayQueue<>();
}
@Override
public int size() {
if (queueA.isEmpty() && queueB.isEmpty()) {
return 0;
} else if (!queueA.isEmpty()) {
return queueA.size();
} else {
return queueB.size();
}
}
@Override
public boolean isEmpty() {
return queueA.isEmpty() && queueB.isEmpty();
}
@Override
public void push(E element) {
if (queueA.isEmpty() && queueB.isEmpty()) {
queueA.offer(element);
} else if (!queueA.isEmpty()) {
queueA.offer(element);
} else {
queueB.offer(element);
}
}
@Override
public E pop() {
if (isEmpty()) {
return null;
}
E ret = null;
if (!queueA.isEmpty()) {
while (queueA.size() != 1) {
queueB.offer(queueA.poll());
}
ret = queueA.poll();
} else {
while (queueB.size() != 1) {
queueA.offer(queueB.poll());
}
ret = queueB.poll();
}
return ret;
}
@Override
public E peek() {
if (isEmpty()) {
return null;
}
E ret = null;
if (!queueA.isEmpty()) {
while (queueA.size() != 1) {
queueB.offer(queueA.poll());
}
ret = queueA.poll();
queueB.offer(ret);
} else {
while (queueB.size() != 1) {
queueA.offer(queueB.poll());
}
ret = queueB.poll();
queueA.offer(ret);
}
return ret;
}
@Override
public void clear() {
queueA.clear();
queueB.clear();
}
@Override
public Iterator<E> iterator() {
if (isEmpty()) {
return queueA.iterator();
} else if (!queueA.isEmpty()) {
return queueA.iterator();
} else {
return queueB.iterator();
}
}
@Override
public String toString() {
if (isEmpty()) {
return "[]";
} else if (!queueA.isEmpty()) {
return queueA.toString();
} else {
return queueB.toString();
}
}
}
1.4循环队列ArrayLoopQueue
1.4.1循环队列ArrayLoopQueue的定义
该循环队列的实现思想也是动态数组 但是由于操作元素的特殊性,并不能直接由ArrayList或ArrayQueue实现 所以从头开始定义ArrayLoopQueue
1.4.2ArrayLoopQueue类
package P2.线性结构;
import P1.接口.Queue;
import java.util.Iterator;
//循环队列
public class ArrayLoopQueue<E> implements Queue<E> {
private E[] data; //存储数据的容器
private int front; //队首指针(实际上就是数组中的索引角标)
private int rear; //队尾指针
private int size; //元素的个数 (f < r r-f ; r < f r+L-f)
private static int DEFAULT_CAPACITY = 10; //默认容量
public ArrayLoopQueue() {
data = (E[]) new Object[DEFAULT_CAPACITY + 1];
front = 0;
rear = 0;
size = 0;
}
@Override
public void offer(E element) {
//满了没
if ((rear + 1) % data.length == front) {
resize(data.length * 2 - 1);
}
data[rear] = element;
rear = (rear + 1) % data.length;
size++;
}
@Override
public E poll() {
//空不空
if (isEmpty()) {
throw new IllegalArgumentException("queue is null");
}
E ret = data[front];
front = (front + 1) % data.length;
size--;
if (size <= (data.length - 1) / 4 && data.length - 1 > DEFAULT_CAPACITY) {
resize(data.length / 2 + 1);
}
return ret;
}
@Override
public E peek() {
return null;
}
private void resize(int newLen) {
E[] newData = (E[]) new Object[newLen];
int index = 0;
for (int i = front; i != rear; i = (i + 1) % data.length) {
newData[index++] = data[i];
}
data = newData;
front = 0;
rear = index;
}
@Override
public boolean isEmpty() {
return front == rear;
}
@Override
public void clear() {
data = (E[]) new Object[DEFAULT_CAPACITY];
size = 0;
front = 0;
rear = 0;
}
@Override
public int size() {
return size;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
if (isEmpty()) {
sb.append(']');
return sb.toString();
}
for (int i = front; i != rear; i = (i + 1) % data.length) {
sb.append(data[i]);
if ((i + 1) % data.length == rear) {
sb.append(']');
} else {
sb.append(',');
sb.append(' ');
}
}
return sb.toString();
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (this == o) {
return true;
}
if (o instanceof ArrayLoopQueue) {
ArrayLoopQueue<E> other = (ArrayLoopQueue<E>) o;
if (size != other.size) {
return false;
}
int i = front;
int j = other.front;
while (i != rear) {
if (!data[i].equals(other.data[j])) {
return false;
}
i = (i + 1) % data.length;
j = (j + 1) % other.data.length;
}
return true;
}
return false;
}
@Override
public Iterator<E> iterator() {
return new ArrayLoopQueueIterator();
}
class ArrayLoopQueueIterator implements Iterator<E> {
private int cur = front;
@Override
public boolean hasNext() {
return cur != rear;
}
@Override
public E next() {
E ret = data[cur];
cur = (cur + 1) % data.length;
return ret;
}
}
}
1.5双端队列
1.5.1双端队列的定义
双端队列(double ended queue ,deque) 是限定插入和删除操作在表的两端进行的线性表 是一种具有队列和栈的性质的数据结构
1.5.2ArrayDeque类
package p2.线性结构;
import p1.接口.Queue;
import java.util.Iterator;
public class ArrayQueue<E> implements Queue<E> {
private ArrayList<E> list;
public ArrayQueue() {
list = new ArrayList<>();
}
@Override
public void offer(E element) {
list.add(list.size(), element);
}
@Override
public E poll() {
return list.remove(0);
}
@Override
public E element() {
return list.get(0);
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public void clear() {
list.clear();
}
@Override
public int size() {
return list.size();
}
@Override
public Iterator<E> iterator() {
return list.iterator();
}
@Override
public String toString() {
return list.toString();
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (this == o) {
return true;
}
if (o instanceof ArrayQueue) {
ArrayQueue other = (ArrayQueue) o;
return list.equals(other.list);
}
return false;
}
}