一、栈存储
栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
代码实现:
/**
* @Author: Stephen
* @Date: 2019/12/17 22:47
* @Content: 实现栈存储
*/
public class Mystack {
/**
* 实现方式:
* 底层使用数组 压入元素 在数组最后一位添加数据
* 取出栈点元素
*/
// 栈的底层使用数组存储数据
Object[] elements;
public Mystack(){
elements = new Objects[0];
}
// 压入元素
public void push(Objects element){
Object[] newarr = new Object[elements.length+1];
for (int i=0;i<elements.length;i++){
newarr[i] = elements[i];
}
newarr[elements.length] = element;
elements = newarr;
}
// 取出栈顶元素
public Object pop(){
if (elements.length==0){
throw new RuntimeException("栈为空");
}
// 去除数组的最后一个元素
Object element = elements[elements.length-1];
// 创建一个新的数组
Object[] newArr = new Object[elements.length-1];
// 原数组中除了最后一个元素的其它元素都放入到新数组中
for (int i=0;i<elements.length-1;i++){
newArr[i] = elements[i];
}
// 替换数组
elements = newArr;
// 返回栈顶元素
return element;
}
// 查看栈顶元素
public Object peek() {
return elements[elements.length-1];
}
// 判断栈是否为空
public boolean isEmpty(){
return elements.length==0;
}
}
二、队列存储
定义:队列,又称为伫列(queue),是先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。
和堆栈一样的,也有两种操作,进队(EnQueue)和出队(DeQueue),对于空队列进行出队操作会造成下溢出(underflow),相应的堆满队列进行进队操作为发生上溢出
代码实现
/**
* @Author: Stephen
* @Date: 2019/12/17 23:17
* @Content: 实现队列
*/
public class MyQueue {
Object[] elements;
public MyQueue(){
elements = new Objects[0];
}
/**
* 入队
* @param element
*/
public void add(Object element){
Object[] newarr = new Object[elements.length+1];
for (int i=0;i<elements.length;i++){
newarr[i] = elements[i];
}
newarr[elements.length] = element;
elements = newarr;
}
/**
* 出队 : 将对头的取出
*/
public Object poll(){
if (elements.length==0){
throw new RuntimeException("队列为空");
}
// 把数组中的第0个元素取出
Object element = elements[0];
Object[] newArr = new Object[elements.length-1];
for (int i=0;i<newArr.length;i++){
newArr[i] = elements[i+1];
}
// 替换数组
elements = newArr;
return element;
}
public boolean isEmpty(){
return elements.length==0;
}
}
三、单链表存储
单链表是链表的其中一种基本结构。一个最简单的结点结构如图所示,它是构成单链表的基本结点结构。在结点中数据域用来存储数据元素,指针域用于指向下一个具有相同结构的结点。
因为只有一个指针结点,称为单链表。
单链表中三个概念需要区分清楚:分别是头指针,头节点和首元节点。
-
头结点:有时,在链表的第一个结点之前会额外增设一个结点,结点的数据域一般不存放数据(有些情况下也可以存放链表的长度等信息),此结点被称为头结点。
若头结点的指针域为空(NULL),表明链表是空表。头结点对于链表来说,不是必须的,在处理某些问题时,给链表添加头结点会使问题变得简单。
首元结点:链表中第一个元素所在的结点,它是头结点后边的第一个结点。 -
头指针:永远指向链表中第一个结点的位置(如果链表有头结点,头指针指向头结点;否则,头指针指向首元结点)。
-
头结点和头指针的区别:头指针是一个指针,头指针指向链表的头结点或者首元结点;头结点是一个实际存在的结点,它包含有数据域和指针域。两者在程序中的直接体现就是:头指针只声明而没有分配存储空间,头结点进行了声明并分配了一个结点的实际物理内存。
单链表中可以没有头结点,但是不能没有头指针!
头节点的引入能使链表对第一个元素的删除和插入和其他元素相同,不用另外说明,使得代码更加简洁。
代码实现
/**
* @Author: Stephen
* @Date: 2019/12/17 23:45
* @Content: 单链表的实现
*/
public class Node {
// 节点内容
Object data;
// 下一个节点
Node next;
public Node(Object data){
this.data = data;
}
// 为节点追加节点
public Node append(Node node){
// 想要在一个节点无线追加
// 判断当前节点是否有元素
Node currentNode = this;
// 循环向后找
while (true){
// 通过当前节点找到下一个节点
Node nextNode = currentNode.next;
// 如果下一个节点为空 则表示最后一个节点
if (nextNode == null){
// 当前节点为最后一个节点
break;
}
// 赋给当前节点
currentNode = nextNode;
}
// 把需要追加的节点追加为找到当前节点的下一个节点
currentNode.next = node;
return this;
}
// 获取下一个节点
public Node next(){
return this.next;
}
// 获取节点中的数据
public Object getData(){
return this.data;
}
// 判断当前节点是否是最后一个节点
public boolean isLast(){
return next==null;
}
}