实现链栈功能
完整代码
public class StackByLinkTest {
public static void main(String[] args) {
StackByLink sbl = new StackByLink();
LinkNode one = new LinkNode(1);
LinkNode two = new LinkNode(2);
LinkNode three = new LinkNode(3);
LinkNode frou = new LinkNode(4);
LinkNode five = new LinkNode(5);
sbl.push(one);
sbl.push(two);
sbl.push(three);
sbl.push(frou);
sbl.push(five);
sbl.list();
System.out.println("---------------------");
int value = sbl.pop();
System.out.println("出栈的值为:" + value );
sbl.list();
}
}
// 定义链栈的对象
class StackByLink{
private LinkNode head = new LinkNode(-1);
private LinkNode top = head;
public boolean isEmpty() {
return head.next == null;
}
//入栈
public void push(LinkNode value) {
while(true) {
if(top.next == null) {
break;
}
top = top.next;
}
top.next = value;
top = value;
}
//遍历
public void list() {
if(isEmpty()) {
System.out.println("该链栈为空" );
return;
}
//这里有个我认为的小坑,遍历的时候如果将top已经退回到第一个,那么出栈的时候无法正确出栈
//所以再设置一个傀儡节点,替代top节点进行操作,防止top节点在出栈的时候无法正确指向
LinkNode pre = head;
LinkNode lTop = top;
while(lTop != head) {
if(pre.next == lTop) {
System.out.println(lTop);
lTop = pre;
pre = head;
}
if(pre.next != lTop) {
pre = pre.next;
}
}
}
//出栈
public int pop() {
if(isEmpty()) {
System.out.println("链栈为空,无法出栈");
return 0;
}
LinkNode pre = head;
while(pre.next != top) {
if(pre.next != null) {
pre = pre.next;
}
}
int value = top.num;
//出栈后,将top指针回退到前一个节点之上
top = pre;
return value;
}
}
//定义链栈节点对象
class LinkNode{
public int num;
public LinkNode next;
public LinkNode(int num) {
this.num = num;
}
@Override
public String toString() {
return "LinkNode [num=" + num + "]";
}
}
部分代码
- 入栈操作
public void push(LinkNode value) {
while(true) {
if(top.next == null) {
break;
}
top = top.next;
}
//在链栈最末端添加新数据
top.next = value;
//将top指针指向新数据
top = value;
}
对比单链表的添加操作,链栈的入栈操作并没有太多区别,只是要将top指针指向新的节点,以便在遍历和出栈时候,达到栈的特点
- 出栈操作
public int pop() {
//先判空是否是空栈
if(isEmpty()) {
System.out.println("链栈为空,无法出栈");
return 0;
}
//创造一个傀儡指针,并且找到top的前一个节点
LinkNode pre = head;
while(pre.next != top) {
if(pre.next != null) {
pre = pre.next;
}
}
//将要出栈的节点的值赋值给value
int value = top.num;
//出栈后,将top指针回退到前一个节点之上
top = pre;
return value;
}
对比单链表的删除操作,链栈只能从栈顶来删除节点,不可删除非栈顶节点之外的节点
- 遍历
public void list() {
if(isEmpty()) {
System.out.println("该链栈为空" );
return;
}
//这里有个我认为的小坑,遍历的时候如果将top已经退回到第一个,那么出栈的时候无法正确出栈
//所以再设置一个傀儡节点,替代top节点进行操作,防止top节点在出栈的时候无法正确指向
LinkNode pre = head;
LinkNode lTop = top;
//如果没有到栈底则继续查找
while(lTop != head) {
//和出栈一样,需要把ltop的前一个节点找到,并且进行前移操作
if(pre.next == lTop) {
System.out.println(lTop);
lTop = pre;
pre = head;
}
// 如果还没到ltop的前一个节点,继续查找
if(pre.next != lTop) {
pre = pre.next;
}
}
}
总结
- 链栈有栈的特性,也有链表的特性,不存在满栈,也符合栈的先进后出原则