Java自定义实现链栈
一:写前的认识
栈这种数据结构相信大家都比较熟悉的,节点是先进后出,jdk中的给我们提供的实现的,使用的时候直接使用就可以了,但是我们不仅仅是停留在会使用,动手自己实现以下,可以帮助自己更好的理解。关于栈的一些基本的知识就不在介绍了.是一种被限制的线性表.栈顶的指针是这里实现各种操作的关键.以及如何构造栈这种数据结构的?删除和添加元素都是在栈顶进行的.
就是数据结构中说的数据域和指针域.
jdk的实现:java.util.Stack(底层是基于数组实现的,是线程安全的)和java.util.LinkedList
栈的常用的操作--->
1:初始化:通常是一个构造器.
2:返回栈的大小:返回栈中数据元素的个数.
3:入栈:向栈的栈顶插入一个元素,栈的长度+1
4:出栈从栈的栈顶删除一个数据元素,栈的长度-1,这个方法通常是返回被删除的元素.
5:访问栈顶的元素:返回栈顶的数据元素,但是不删除元素.
6:判断栈是否为空:该方法判断栈是否为空,就是判断栈里面的size的元素个数.
7:清空栈:就是将栈顶指针引用为空.同时size=0.
实现的关键:使用一个指引用top来记录当前的栈顶的元素.top引用变量永远就引用栈顶元素.
二:通过前面的分析我们来设计我们的实现思路---->
解决链表的指针域和数据域的方法.这里由于要访问外部的属性,我们使用非静态内部类来完成链表的构建.
源代码如下:
public class LinkedStack<T> {
//定义内部类,表示链栈的节点,保存链栈的数据
private class Node{
//表示栈存放的节点的数据值
private T data ;
//存放当前节点对下一个节点的引用--可以说是指向写一个节点的指针
private Node next;
//定义无参数的构造方法
@SuppressWarnings("unused")
public Node(){
}
//用于初始化链栈
public Node(T data,Node next){
this.data=data;
this.next=next;
}
}
//定义Top变量引用链栈的栈顶的元素
private Node top;
//定义链栈的大小
private int size;
//返回链栈的大小
public int length(){
return size;
}
//清空链栈
public void clear(){
top=null;
size=0;
}
//创建一个空的链栈
public LinkedStack(){
top=null;
}
//判断一个链栈是否为空
public boolean empty(){
return size==0;
}
//以指定的元素创建一个链栈,这个链栈只有一个元素
public LinkedStack(T element){
top=new Node(element,null);
size++;
}
//返回链栈的栈顶的元素,但是不删除栈顶的元素
public T peek(){
return top.data;
}
//新的节点进入链栈--添加节点
public void push(T element){
//新增的节点保存对之前栈顶的节点的引用
top=new Node(element,top);
size++;
}
//删除栈顶的元素--删除节点,返回删除的节点
public T pop(){
//判断当前的链栈是否为空
if(top==null){
return null;
}else{
Node oldTop=top;
//将当前的栈顶指针修该为当前节点的下一个节点.
top=top.next;
//释放删除的节点,防止内存溢出
oldTop.next=null;
size--;
return oldTop.data;
}
}
//重写toString()方法,返回jdk那种的链栈的格式[]
public String toString(){
//判断当前的链栈是否为空
if(empty()){
return "[]";
}else{
//遍历当前的链栈
//创建StringBuilder来保存当前遍历的节点
StringBuilder sb=new StringBuilder("[");
for(Node current=top;current!=null;current=current.next){
//依次遍历添加元素
sb.append(current.data.toString()+",");
}
int len=sb.length();
return sb.delete(len-1, len).append("]").toString();
}
}
public static void main(String[] args) {
//实例化自定义的链栈
LinkedStack<String> ls=new LinkedStack<String>("AAA");
System.out.println("链栈的大小:"+ls.length()+" 链栈的输出:"+ls.toString());
//添加元素
ls.push("BBB");
ls.push("CCC");
ls.push("DDD");
System.out.println(ls.toString());
System.out.println(ls.peek());
}
}
运行结果如下:
简单的分析:在我们这个自定义的栈中,栈里面有几个元素,底层就会保存几个节点,这个比顺序栈开辟一块内存空间的利用率还是要高一些的.关键的地方就是栈顶引用变量的正确的引用了.