学习目标:
掌握数据结构栈和队列学习内容:
1、 栈 2、 队列 3、循环队列学习时间:
2021年7月4日学习产出:
1、 技术笔记 1 遍 2、CSDN 技术博客 1 篇栈Stack
栈也是一种线性数据结构规定只能从栈顶添加元素,也只能从栈顶取出元素
栈是一种后进先出的数据结构
Last In First Out(LIFO)
栈的具体实现
Stack
void push(T ele) //入栈
T pop() //出栈并返回元素
T peek() //返回栈顶元素但不删除
boolean isEmpty() //判断是否为空
int getSize() //获取栈内元素个数
public class MyStack<T> implements Stack<T> {
//栈数据容器
MySelfArray<T> myArray;
public MyStack() {
this(10);
}
public MyStack(int capacity) {
myArray = new MySelfArray<>(capacity);
}
@Override
public boolean isEmpty() {
return myArray.isEmpty();
}
@Override
public int getSize() {
return myArray.getSize();
}
@Override
public void push(T ele) {
myArray.addTail(ele);
}
@Override
public T pop() {
return myArray.removeTail();
}
@Override
public T peek() {
return myArray.getlastElement();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
if (this.isEmpty()){
return null;
}
sb.append("初始容积是:" + myArray.getCapacity() + ",实际存放元素个数是:" + this.getSize() + ",内容如下");
while (!this.isEmpty()) {
sb.append(this.pop() + "<<<");
}
return sb.substring(0, sb.lastIndexOf("<") - 2);
}
public static void main(String[] args) {
MyStack<Integer> myStack = new MyStack<>(20);
for (int i = 0; i < 10; i++) {
myStack.push(i + 10);
}
System.out.println("栈顶元素为" + myStack.peek());
System.out.println(myStack);
}
}
时间复杂度分析
void push(T ele) //O(1)
T pop() //O(1)
T peek() //O(1)
boolean isEmpty() //O(1)
int getSize() //O(1)
队列Queue
队列也是一种线性数据结构 只能从一端(队尾)添加元素,从另一端(队首)取出元素。
队列的实现
Queue<E>
void enqueue(T ele);//入队操作 O(1)
T dequeue();//出队操作 O(n)原因时在出队时,数组后面的元素都要进行前移。
T getFront();//获取队首元素 O(1)
int getSize();//获取队列中元素个数 O(1)
boolean isEmpty();//判断队列是否为空 O(1)
public class MyQueue<T> implements Queue<T> {
private MySelfArray<T> myArray;
public MyQueue() {
this(10);
}
public MyQueue(int capacity) {
myArray = new MySelfArray<>(capacity);
}
@Override
public void enqueue(T ele) {
myArray.addTail(ele);
}
@Override
public T dequeue() {
return myArray.removeHead();
}
@Override
public T getFront() {
return myArray.getfirstElement();
}
@Override
public int getSize() {
return myArray.getSize();
}
@Override
public boolean isEmpty() {
return myArray.isEmpty();
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[队首");
if (this.isEmpty()){
return null;
}
while (!this.isEmpty()){
sb.append(this.dequeue()+",");
}
// 切割 从0开始 到最后一个","(不包括)
String res = sb.substring(0, sb.lastIndexOf(","));
return res+"队尾]";
}
public static void main(String[] args) {
Queue<Integer> queue = new MyQueue<>();
for (int i = 0; i < 100; i++) {
queue.enqueue(i + 10);
}
if (queue.isEmpty()) {
return;
} else {
System.out.println("队首元素是:" + queue.getFront());
System.out.println(queue);
}
}
}
循环队列
为了解决前移的问题,可以使用front记录队首位置,使用tail记录队尾位置,这就时循环队列。
循环队列的实现
LoopQueue<E>
void enqueue(T ele);//入队操作 O(1)
T dequeue();//出队操作 O(1)
T getFront();//获取队首元素 O(1)
int getSize();//获取队列中元素个数 O(1)
boolean isEmpty();//判断队列是否为空 O(1)
public class LoopQueue<T> {
private T[] data; // 数据容器
private int size; // 队列中元素个数
private int front; // 队首指针
private int tail; // 队尾指针
public LoopQueue() {
this(10);
}
public LoopQueue(int capacity) {
this.data = (T[]) new Object[capacity + 1];
this.size = 0;
this.front = 0;
this.tail = 0;
}
//容器容积
public int getCapacity() {
return data.length;
}
//实际存放元素个数
public int getSize() {
return this.size;
}
//判断队列是否为空
public boolean isEmpty() {
return this.size == 0;
//return this.front == this.tail;
}
//更改容积
public void resize(int newcapacity) {
T[] newData = (T[]) new Object[newcapacity];
for (int i = 0; i < this.size; i++) {
newData[i] = this.data[(this.front + i) % this.getCapacity()];
}
this.data = newData;
this.front = 0;
this.tail = this.size;
}
//入队操作
public void enqueue(T ele) {
//判断队列是否已满
if ((this.tail + 1) % this.getCapacity() == this.front) {
//扩容操作
resize(this.getCapacity() * 2 - 1);
}
this.data[this.tail] = ele;
this.size++;
this.tail = (this.tail + 1) % this.getCapacity();
}
//出队操作
public T dequeue() {
if (this.isEmpty()) {
throw new IllegalArgumentException("this equeue is empty!");
}
T result = this.data[this.front];
this.size--;
this.front = (this.front + 1) % this.getCapacity();
//缩容操作
if (this.getSize() == this.getCapacity() / 4 && this.getCapacity() / 2 > 1) {
resize((this.getCapacity() + 1) / 2);
}
return result;
}
//获取队首元素
public T getFront() {
if (this.isEmpty()) {
throw new IllegalArgumentException("this equeue is empty!");
}
return this.data[this.front];
}
public static void main(String[] args) {
LoopQueue<Integer> loopQueue = new LoopQueue<>(1000);
for (int i = 0; i < 10000; i++) {
loopQueue.enqueue(i);
if (i % 3000 == 0) {
while (!loopQueue.isEmpty()) {
System.out.println(loopQueue.dequeue());
}
}
}
while (!loopQueue.isEmpty()) {
System.out.println(loopQueue.dequeue());
}
}
}