1. 什么是栈?
栈(stack)是限定仅在表尾进行插入和删除操作的线性表。
2. 栈的特点:
1.) 栈又称为后进先出(Last In First out)的线性表,栈元素具有线性关系,即前驱后继关系。
2.) 栈的特殊之处在于:它的栈底是固定的,只允许在栈顶进行插入和删除操作。
3. 栈的顺序存储结构(Java数组实现):
// 栈的数组实现, 底层使用数组:
public class ArrayStack<T> {
private Object[] arr; // 数组首元素作为栈底,因为它变化小
private int length;
// 数据初始化
public ArrayStack(){
arr = new Object[16];
length = 0;
}
// 元素入栈
public boolean push(T data) {
if (length >= arr.length) { // 判断是否需要进行数组扩容
resize();
}
arr[length++] = data;
return true;
}
// 元素出栈
@SuppressWarnings("unchecked")
public T pop() {
if (length == 0) {
return null;
}
return (T) arr[--length];
}
// 将数组中的数据置为null, 方便GC进行回收
public void clear() {
for (int i = 0; i < length; i++) {
arr[length] = null;
}
length = 0;
}
// 数组扩充容量
private void resize() {
Object[] temp = new Object[arr.length * 3 / 2 + 1];
for (int i = 0; i < length; i++) {
temp[i] = arr[i];
arr[i] = null;
}
arr = temp;
}
// 获取栈中元素个数
public int length() {
return length;
}
// 判断数组是否为空
public boolean isEmpty() {
return length == 0;
}
// 打印栈中元素
public String toString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
sb.append(arr[i].toString());
if (i != length - 1) {
sb.append(", ");
}
}
return sb.toString();
}
public static void main(String[] args) {
ArrayStack<Integer> stack = new ArrayStack<Integer>();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
stack.push(i); // 入栈
}
long temp = System.currentTimeMillis();
System.out.println("push time: " + (temp - start));
while (stack.pop() != null){
; // 出栈
}
System.out.println("pop time: " + (System.currentTimeMillis() - temp));
}
}
运行时间:
push time: 257ms
pop time: 5ms
4. 栈的链式存储结构(Java链表实现):
// 结点元素
public class Node<T> {
private Node<T> prev; // 记住当前结点的前一结点
private T data; // 数据域
public Node() {
}
public Node(T data, Node<T> prev) {
this.data = data;
this.prev = prev;
}
public Node<T> getPrev() {
return prev;
}
public void setPrev(Node<T> prev) {
this.prev = prev;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
// 栈的链表实现, 底层使用单链表:
public class LinkedStack<T> {
private Node<T> top; // 栈顶指针(链表尾结点)
private int size; // 栈的长度
// 数据初始化
public LinkedStack() {
top = null;
size = 0;
}
// 结点入栈
public boolean push(T data) {
Node<T> newNode = new Node<T>(data,top); // 将top设置为新节点的前驱结点
top = newNode; // 将新结点设置为栈顶指针
size++;
return true;
}
// 结点出栈
public T pop() {
if (top != null) {
Node<T> tempNode = top;
top = top.getPrev(); // 将栈顶指针的前驱结点设置为栈顶指针
size--;
return tempNode.getData();
}
return null;
}
// 判断栈是否为空
public boolean isEmpty() {
return size == 0;
}
// 获取栈的长度
public int length() {
return size;
}
// 打印栈中元素
public String toString() {
Node<T> node = top;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < size; i++) {
sb.append(node.getData().toString());
if (i != size - 1) {
sb.append(", ");
}
node = node.getPrev();
}
return sb.reverse().toString();
}
public static void main(String[] args) {
LinkedStack<Integer> stack = new LinkedStack<Integer>();
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
stack.push(i); // 入栈
}
long temp = System.currentTimeMillis();
System.out.println("push time: " + (temp - start));
while (stack.pop() != null){
; // 出栈
}
System.out.println("pop time: " + (System.currentTimeMillis() - temp));
}
}
运行时间:
push time: 986ms
pop time: 15ms
5. 两种实现方式比较:通过入栈和出栈时间比较可以看出,数组实现在性能上还是有明显优势的,这是因为数组实现的栈在增加和删除元素时并不需要移动大量的元素,只是在扩大数组容量时,需要进行拷贝。然而链表实现的栈在入栈时需要将数据包装成Node,出栈时需要从Node中取出数据,同时还要维护栈顶指针和前驱指针。
6. JDK API中的栈:
1.) java.util.Stack: 一个普通的顺序栈,底层基于数组实现。这个类是线程安全的。
2.) java.util.LinkedList: 一个双向链表,线程不安全,可以当做栈来使用。在多线程环境下可以使用Collections类的工具方法将其改造成线程安全类。
3.) 两个类都提供了push(),pop(),peek()等方法。
分享到:
相关推荐
大话数据结构 .pptx
《大话数据分析:Tableau数据可视化实战》的数据集是一份重要的资源,对于想要学习和提升Tableau数据可视化技能的人来说极具价值。Tableau是一款强大的商业智能工具,它允许用户通过直观的拖放界面来探索和可视化...
串是由字符组成的特殊线性表,支持字符串操作,如连接、子串查找、替换等。在编程语言中,字符串处理是不可或缺的部分。 数和二叉树是数据结构的重要组成部分。二叉树是一种每个节点最多有两个子节点的树形结构,常...
只供博主个人学习
大数据也可以定义为来自各种来源的大量非结构化或结构化数据。从学术角度而言,大数据的出现促成广泛主题的新颖研究。这也导致各种大数据统计方法的发展。大数据并没有统计学的抽样方法;它只是观察和追踪发生的事情...
栈是一种特殊的线性数据结构,其特点是后进先出(LIFO)。即最后进入栈的数据总是最先被访问。在栈中,所有插入或删除操作都发生在栈的一端,这一端被称为栈顶(top),而另一端被称为栈底(base)。 #### 栈的操作...
个人自用
基于《大话数据结构》进行数据结构的学习
Android之大话设计模式——:抽象工厂模式借鉴.pdf
大话Oracle RAC:集群、高可用性、备份与恢复(带目录清晰中文完整版)
线性表是一种基本的数据结构,它由顺序存储的元素序列组成,通常可以是数组或链表。在Java中,我们可以利用ArrayList类来实现线性表,因为它提供了动态增长的特性,便于插入和删除元素。 首先,我们需要理解线性表...
3. **栈**:后进先出(LIFO)的数据结构,常用操作为压栈(push)和弹栈(pop)。 4. **队列**:先进先出(FIFO)的数据结构,常用操作为入队(enqueue)和出队(dequeue)。 5. **哈希表**:通过哈希函数快速定位...
大话数据结构 JAVA版本源代码.zip
大话Oracle RAC:集群、高可用性、备份与恢复。 此书被认为不可多得的好资料之一:大话Oracle RAC(PDF经典),看完之后深有感触,发出来共享一下。
Android之大话设计模式——:抽象工厂模式参考.pdf
要学好数据结构 但是面对枯燥乏味的数据结构内容,是不是很无聊,想睡觉,想放弃 试试大话这个资料
读书笔记大化设计模式、大话数据结构
《大话数据结构》源码(Python版).zip