栈---单向链表模拟栈的实现

上一篇大致的介绍了栈,并使用数组的方式模拟了栈的实现。
这次使用单向链表来模拟栈的实现

用单向链表实现栈的思路:
1.使用单向链表来模拟栈
2.创建节点类,创建一个top指针表示栈顶,初始化为null
3.入栈操作:当有数据加入到栈中时,将节点添加到链表的最后,并将top指针指向这个节点
4.出栈操作:当有数据出栈时,将最后的节点出栈(将最后的节点从链表中删除),并将top指向最后节点的前一个节点
5.遍历:栈的遍历是先进后出,而链表是先进先出,所以要先将链表进行反转,然后再打印,来实现栈的遍历

Java代码实现:

import java.util.Scanner;

public class LinkedListStackDemo {
public static void main(String[] args) {
	// TODO Auto-generated method stub

	//测试
	//创建单向链表实现的栈
	LinkedListStack linkedListStack = new LinkedListStack();
	String key = "";//用来接收用户的输入
	boolean loop = true;//控制是否退出菜单
	Scanner input = new Scanner(System.in);
	while(loop) {
		System.out.println();
		System.out.println("show:表示显示栈!");
		System.out.println("exit:退出程序!");
		System.out.println("push:表示添加数据到栈(入栈)!");
		System.out.println("pop:表示从栈中取出数据(出栈)!");
		
		System.out.println("请输入你的选择~~~");
		key = input.next();
		switch(key) {
		case "show":
			linkedListStack.list();
			break;
		case "push":
			System.out.println("请输入数据");
			String value = input.next();
			Node node = new Node(value);
			linkedListStack.push(node);
			break;
		case "pop":
			try {
				Node res = linkedListStack.pop();
				System.out.println("出栈的节点是:"+res);
			}catch(Exception e){
				//如果是一个空栈
				System.out.println(e.getMessage());
			}
			break;
		case "exit":
			input.close();
			loop = false;
			break;
		default:
			break;
		}
	}
	System.out.println("程序退出!!!");
	
}

}
//创建一个LinkedListStack类来管理节点
class LinkedListStack{
	// 先初始化一个头结点,头结点不动
	private Node head = new Node("");
	//定义一个节点,代表栈顶所指节点
	private Node top = null;

	// 创建一个获取头结点的方法
	public Node getHead() {
		return head;
}

// 栈空
public boolean isEmpty() {
	return top == null;
}

//添加节点到这个单向链表实现的栈中,即入栈
public void push(Node node) {
	//因为头结点不能动,所以需要一个辅助节点来完成
	Node temp = head;
	//对链表进行遍历,遍历到最后一个节点,然后进行添加节点
	while(true) {
		//判断是否为节点的最后
		if(temp.next == null) {
			//当为空时,说明已经是最后一个节点
			break;
		}
		//如果不为空,则指针向后移动
		temp = temp.next;
	}
	//当退出while循环时,说明到了最后一个节点
	//将节点添加到链表的最后
	temp.next = node;
	//将top指向这个节点
	top = node;
}

//删除节点从单向链表实现的栈中,即出栈
public Node pop() {
	//将top指针指向的节点出栈
	//因为出栈后,top指针需要向前移动,所以需要一个辅助指针完成出栈
	Node tmp = top;
	//将top指针向前移动一个
	//需要重新遍历链表找到top节点的前一个节点,再由top指针指向这个节点
	Node h = head;
	while(true) {
		//找到top节点的前一个节点
		if(h.next == top) {
			//说明找到了这个节点
			break;
		}
		//如果不是,则指针向后移动
		h = h.next;
	}
	//退出循环后,找到top节点的前一个节点,对top节点进行删除
	h.next = top.next;
	//将top指针指向这个节点,完成top指针的前移动作
	top = h;
	return tmp;
}

//显示栈的情况[遍历栈],遍历时,需要从栈顶开始显示数据,即从链表尾遍历链表
//将链表进行反转,然后再打印链表
public void list() {
	// 判断链表是否为空
	if (head.next == null) {
		System.out.println("链表为空!!!");
		return;
	}
	// 因为头结点不能动,需要辅助变量来遍历
	reverseList(head);
	Node temp = head.next;
	while (true) {
		// 判断是否到链表最后
		if (temp == null) {
			break;
		}
		// 输出节点信息
		System.out.println(temp);
		// 将temp后移
		temp = temp.next;
	}
}

//栈的遍历需要先将链表进行反转
//链表反转
public void reverseList(Node head) {
	// 如果当前链表为空,或者只有一个节点,无需反转,直接返回
	if (head.next == null || head.next.next == null) {
		return;
	}
	// 定义一个辅助的指针(变量),帮助遍历原来的链表
	Node cur = head.next;
	// 定义一个变量存储当前节点的下个节点,即指向当前节点[cur]的下个节点
	Node next = null;
	//定义一个新链表的头结点
	Node reverseHead = new Node("");
	// 遍历原来的链表,每遍历一个节点就将其取出,并放在新的链表reverseHead的最前端
	while (cur != null) {
		// 暂时保存当前节点的下一个节点(后续需要使用)
		next = cur.next;
		// 将cur的下个节点指向新的链表的最前端
		cur.next = reverseHead.next;
		// 将cur连接到新的链表上
		reverseHead.next = cur;
		// 让cur后移
		cur = next;
	}
	// 将head.next指向reverseHead.next,实现单链表的反转
	head.next = reverseHead.next;
}

}

//先创建一个节点类Node
class Node{
	public String value;//存储的数据
	public Node next;//下一个节点
	
	//构造器
	public Node(String value) {
		this.value = value;
	}

//重新toString
	@Override
	public String toString() {
		return "Node [value = "+value+"]";
		}
}
发布了40 篇原创文章 · 获赞 2 · 访问量 3410

猜你喜欢

转载自blog.csdn.net/BEYONDmonster/article/details/100558568
今日推荐