栈Stack
栈是一种线性数据结构
先进后出First Out Last In 即只能从栈顶添加元素或取出元素
基于数组实现栈:(详细注解)
package com.ffyc.datastructure;
import java.util.Random;
//基以数组作为栈的底层数组结构 用来存放栈中元素 实现栈接口 重写方法
public class ArrayStack<T>implements MyStack<T> {//注意实现的是MyStack<T>而不只是MyStack
MyArray<T> data;//栈中的数组容器 也可以写成T
int size;//实际存放元素的个数 也写可不写 因为data里面也可以拿到
//构造函数初始化 new一个数组
public ArrayStack() {
this.data = new MyArray<T>();
this.size = 0;
}
@Override
public void push(T ele) {
this.data.addTail(ele);//尾部添加 size永远指向待插入元素的位置 时间复杂度O(1)
this.size++;
}
@Override
public T pop() {
T result= this.data.removeTail();
if (result!=null){
this.size--;
}
return result;
}
@Override
public T peek() {
if (this.isEmpty()){
return null;
}
return this.data.getEleByIndex(this.size-1);
}
@Override
public int getSize() {
return this.size;
}
@Override
public boolean isEmpty() {
return this.size==0;//等于0返回 true是空的 不等于0返回false 不是空的
}
public static void main(String[] args) {
ArrayStack<Integer> arrayStack=new ArrayStack<>();
int count=10;
Random random=new Random();
for (int i=0;i<count;i++){
int num=random.nextInt(10) ;
System.out.print(num+",");
arrayStack.push(num);//入栈
}
System.out.println("\n-------------");
while (!arrayStack.isEmpty()){
System.out.println(arrayStack.pop());//出栈
}
}
}
测试结果:
时间复杂度分析:
入栈、出栈、查看栈顶元素、判空和获取栈中元素的个数 都是O(1)
队列Queue
队列也是一种线性数据结
先进先出,从队尾添加元素,从队首取出元素
基于数组实现队列:
package com.ffyc.datastructure;
import java.util.Queue;
import java.util.Random;
//以数组为底层数据结构 来存储队列中存放的元素
public class ArrayQueue<T> implements MyQueue<T> {
MyArray<T> data;
int size;
public ArrayQueue() {
this.data=new MyArray<T>();
this.size=0;
}
@Override
public void enqueue(T ele) {
this.data.addTail(ele);//队尾添加时间复杂度O(1)
this.size++;
}
@Override
public T dequeue() {
T result=this.data.removeHead();
if (result!=null){
this.size--;
}
return result;
}
@Override
public T getFront() {
return this.data.getEleByIndex(0);
}
@Override
public int getSize() {
return this.size;
}
@Override
public boolean isEmpty() {
return this.size==0;
}
public static void main(String[] args) {
ArrayQueue<Integer> arrayQueue=new ArrayQueue<>();
int count=10;
Random random=new Random();
for (int i=0;i<count;i++){
int num=random.nextInt(10) ;
System.out.print(num+",");
arrayQueue.enqueue(num);//入队
}
System.out.println("\n--------------");
while (!arrayQueue.isEmpty()){//出队
System.out.println(arrayQueue.dequeue()+",");
}
System.out.println("队列是否为空:"+arrayQueue.isEmpty());
}
}
测试结果:
循环队列
普通队列出队操作数组后面的元素都要往前移,时间复杂度就是O(n),为了解决前移问题,就升级出来了循环队列,front记录队首位置,tail记录队尾位置 ,每次出队就front往后移,浪费一个空间换取时间,时间复杂度O(1)
条件有所变化:
1.队列为空
2.队列满
代码实现:
package com.ffyc.datastructure;
import java.util.Random;
//循环队列 增加队首队尾指针
public class CycleQueue<T> implements MyQueue<T> {
T[] data;
int size;
//两个索引 front=tail时队列为空
int front;//头指针(索引)
int tail;//尾指针(索引)
int capacity;//保存容器 方便后面对队列取余
public CycleQueue() {
this(10);
}
public CycleQueue(int capacity) {//初始化
this.capacity=capacity;
data= (T[]) new Object[capacity+1];//创建数组是有意无意浪费一个空间 多创建一个空间
this.size=0;
this.front=0;
this.tail=0;
}
@Override
public void enqueue(T ele) {//入队
if ((this.tail+1)%(this.capacity+1)==this.front){
//如果队满 扩容
resize(2*capacity);
}
this.size+=1;
this.data[this.tail]=ele; //插入
this.tail=(this.tail+1)%(this.capacity+1);//tail往后移
}
//改变容积的方法 扩容或缩容
private void resize(int newCapacity) {
int oldCapacity = this.capacity;
this.capacity = newCapacity;
T[] temp = (T[]) new Object[this.capacity + 1];
for (int i = 0; i < this.size; i++) {
temp[i] = this.data[(this.front + i) % (oldCapacity + 1)];
}
this.data = temp;
this.front = 0;
this.tail = this.size;
}
@Override
public T dequeue() {//出队
if (isEmpty()) {
return null;//如果队列为空 就不能出队
}
//否则出队
T result = this.data[this.front];//保存出队元素 以便最后返回
this.front = (this.front + 1) % (this.capacity + 1);//front后移一位
this.size--;
//缩容
if (this.size == this.capacity / 4 && this.capacity / 2 > 1) {
resize(this.capacity / 2);
}
return result;
}
@Override
public T getFront() {
if (isEmpty()){
return null;//如果队列为空 返回null
}
return this.data[this.front];
}
@Override
public int getSize() {
return this.size;
}
@Override
public boolean isEmpty() {
return this.front==this.tail;
}
public static void main(String[] args) {
CycleQueue<Integer> cycleQueue=new CycleQueue<>(5);
int count =10;
Random random=new Random();
for (int i=0;i<count;i++){
int num=random.nextInt(10) ;
System.out.print(num+",");
cycleQueue.enqueue(num);//入队
}
System.out.println();
System.out.println("队首元素:"+cycleQueue.getFront());
while (!cycleQueue.isEmpty()) {
System.out.println(cycleQueue.dequeue());
}
}
}
测试结果:
!