Java基础 - 栈的链式存储结构及实现

类似的。程序可以采用单链表来保存栈中的所有元素,这种链式的栈也被称为链栈。对于链栈而言,栈顶的元素不断改变,程序只要用一个top引用来记录当前的栈顶元素即可。top引用变量永远引用栈顶元素,在使用一个size变量记录当前栈中包含多少个元素即可。下面是链栈示意图:


1、进栈
对于链栈的进栈操作,程序需要做如下两件事情:
(1)让top引用指向新添加的元素,新元素的next引用指向原来的栈顶元素。
(2)让记录栈内元素的个数size+1.
下面是进栈示意图:

2、出栈
对于链栈的出栈操作,程序需要将栈顶的元素弹出栈,需要做两件事情:
(1)让top引用指向原栈顶元素的下一个元素并释放原栈顶元素。
(2)让记录栈内元素的个数size-1.。
下面是出栈的示意图:

下面是代码实现:

public class LinkStack<T> {
	private class Node{
		private Node next;
		private T data;
		
		@SuppressWarnings("unused")
		public Node(){
		}
		public Node(T element){
			this.data = element;
			this.next = null;
		}
		public Node(T element, Node next){
			this.data = element;
			this.next = next;
		}
	}
	//链栈的长度
	private int size;
	//永远指向栈顶的引用
	private Node top;
	
	public LinkStack(){
		top = null;
		size = 0;
	}
	public LinkStack(T element){
		top = new Node(element);
		size ++;
	}
	
	public int length(){
		return size;
	}
	
	public boolean isEmpty(){
		return size == 0;
	}
	
	//入栈(push)
	public void push(T element){
		top = new Node(element, top);
		size ++;
	}
	//出栈(pop)并返回栈顶元素
	public T pop(){
		Node oldTop = top;
		top = top.next;
		oldTop.next = null;
		size --;
		
		return oldTop.data;
	}
	//peek
	public T peek(){
		return top.data;
	}
	//清空链栈‘
	public void clear(){
		top = null;
		size = 0;
	}
	
	//toString方法
	public String toString(){
		if(isEmpty()){
			return "[]";
		}
		else{
			StringBuffer sb = new StringBuffer("[");
			
			for(Node current = top; current != null; current = current.next){
				sb.append(current.data.toString() + ",");
			}
			return sb.toString().substring(0, sb.length() - 1) + "]";
		}
	}
}

测试类如下:

import com.yc.list.LinkStack;

public class LinkStackTest {
	public static void main(String[] args) {
		LinkStack<Student> stack = new LinkStack<Student>();
		stack.push(new Student("wb", "湖工", 22));
		stack.push(new Student("lp", "湖工", 22));
		stack.push(new Student("ls", "湖工", 22));
		System.out.println( "从栈顶向栈底依次输出链栈:  " + stack);
		System.out.println();  
		
		
		Student s1 = stack.peek();
		System.out.println( "peek的数据元素为:  " + s1);
		System.out.println( "从栈顶向栈底依次输出链栈:  " + stack);
		System.out.println();
		
		Student s2 = stack.pop();
		System.out.println( "pop的数据元素为:   " + s2);
		System.out.println( "从栈顶向栈底依次输出链栈:  " + stack);
		System.out.println();
		
		System.out.println( stack.isEmpty());
		stack.clear();
		System.out.println( stack.isEmpty());
	}
}

测试结果为:



运行上面的程序,LinkStack通常可以正常工作。经过上面的介绍可以看出,为了实现栈这种数据结构,程序有两种实现选择:顺序栈和链栈。
由于栈不需要实现随机存、取的功能,他只需要从栈顶插入、删除元素,因此顺序结构所提供的高效存、取就没有太大的意义,即采用链式结构的实现,

程序同样可以高效的出栈、入栈。对于链栈而言,栈内包含几个元素,底层链式结构就只需保存几个节点,每个节点需要额外添加一个next引用,

这会引起部分空间的浪费。但对于顺序栈来说,程序开始就要在底层开辟一块连续的内存(数组),这种空间浪费其实更大。从空间利用率来看,链栈的

空间利用率要比顺序栈的空间利用率高一些。

Java集合中的栈:
栈也是一种常用的数据结构,因此Java集合框架也提供了栈来工开发者使用。对于Java集合而言,它并未专门提供一个Stack接口,再为
该接口提供了顺序栈、链栈两种实现。
但JAVA集合实际上提供了一下两种栈供开发者使用:
(1)java.util.Stack:它是一个最普通的顺序栈,底层基于数组实现。这个Stack类是线程安全的,在多线程环境下也可以方心使用。
(2)java.util.LinkedList:首先LinkedList是一个双向链表;除此之外,LinkedList还可以作为栈来使用,查看该类的API将会发现,它同样提供了
push(),pop(),peek()这种栈的标志性方法。这表明linkedList是可以当成栈来使用的。但它是线程不安全的,如果需要在多线程的环境下使用它的话,
则应该使用Collections类的工具方法将其“改造”成线程安全的。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值