day4学习 

采用了两种方式实现了栈这个结构

1.数组

2.链表

在链表中对于栈的逆序输出使用了两种方法 第一种方式是对于原来的链表进行逆置输出再重置,第二种方式是直接调用Stack类传入节点类来实现逆序出栈的效果

代码如下:

1数组实现:

package stack;

import java.util.Scanner;

//数组模拟栈
public class ArrayStackDemo {
	public static void main(String[] args) {
         //测试
		//创建一个ArrayStack对象->表示栈
		ArrayStack Stack = new ArrayStack(4);
		String key = "";
		boolean loop = true;//控制是否退出菜单
		Scanner scanner = new Scanner(System.in);
		
		while(loop) {
			System.out.println("show:表示显示栈");
			System.out.println("exit:表示退出程序");
			System.out.println("push:表示添加数据到栈");
			System.out.println("pop:表示出栈");
			System.out.println("请输入你的选择");
			key = scanner.next();
			switch (key) {
			case "show":
				Stack.list();
				break;
			case "exit":
				scanner.close();
				loop = false;
				break;
			case "push":
				System.out.println("请输入一个数");
				int value = scanner.nextInt();
				Stack.push(value);
				break;
			case "pop"://因为可能出现抛出异常的情况所以使用try catch捕获异常
				try {
					int res = Stack.pop();
					System.out.printf("出栈的数据是%d \n", res);
				} catch (Exception e) {
					System.out.println(e.getMessage());
				}
				break;
				default:
					break;
			}
		}
		System.out.println("程序退出了");
	}
}


//定义一个类表示栈结构
class ArrayStack {
	 private int maxSize;//定义栈的最大容量
	 private int[] stack;//数组模拟栈,数据就放在该数组里
	 private int top = -1;//表示栈顶 初始化为 -1
	 
	 //构造器
	 public ArrayStack(int maxSize) {
		 this.maxSize = maxSize;
		 stack = new int[this.maxSize];
	 }
	 //判断栈满
	 public boolean isFull() {
		 return top == maxSize -1;
	 }
	 //判断栈空
	 public boolean isEmpty() {
		 return top == -1;
	 }
	 
	 //入栈
	 public void push(int value) {
		 if(isFull()) {
			 System.out.println("栈满");
			 return;
		 }
		 top++;
		 stack[top] = value;
	 }
	 
	 //出栈
	 public int pop() {
		 if(isEmpty()) {
			throw new RuntimeException("栈空");//方法被终止且runtime异常可以不需要被捕获
		 }
		 int value = stack[top];
		 top--;
		 return value;
	 }
	 
	 //显示栈的情况,遍历时需要从栈顶开始显示数据
	 public void list() {
		 if(isEmpty()) {
				System.out.println("栈空");//方法被终止且runtime异常可以不需要被捕获
			 }
		 
		 for (int i = top; i >= 0; i--) {
			System.out.printf("stack[%d] = %d \n", i,stack[i]);
		}
	 }
	 
	 
	 
}

2.链表实现:

package stack;

import java.util.Stack;

public class LinkedListStackDemo {

	public static void main(String[] args) {
		// 添加测试节点
		Node node1 = new Node(1);
		Node node2 = new Node(2);
		Node node3 = new Node(3);
		Node node4 = new Node(4);
		Node node5 = new Node(5);
		Node node6 = new Node(6);
		// 添加测试链栈 最大长度为5
		LinkedListStack linkedListStack = new LinkedListStack(5);
		linkedListStack.pushNode(node1);
		linkedListStack.pushNode(node2);
		linkedListStack.pushNode(node3);
		linkedListStack.pushNode(node4);
		linkedListStack.pushNode(node5);
		// 栈满测试
		linkedListStack.pushNode(node6);
		// 显示链栈
		// linkedListStack.list1(linkedListStack.getHead());
		linkedListStack.list2(linkedListStack.getHead());

		// 出栈
		linkedListStack.popNode();
		linkedListStack.popNode();
		System.out.println("----------------------");
		// 显示链栈
		// linkedListStack.list1(linkedListStack.getHead());
		linkedListStack.list2(linkedListStack.getHead());

	}

}

class LinkedListStack {
	private Node head = new Node(0);// 初始化一个头结点
	private Node top = head;// 初始情况下栈顶指向head节点
	private int maxSize;// 定义栈的最大容量
	private int count = 0;// 定义了栈的当前容量

	// 构造器 定义了栈的最大容量
	public LinkedListStack(int maxSize) {
		this.maxSize = maxSize;
	}

	// 获取头指针
	public Node getHead() {
		return head;
	}

	// 获取栈顶节点
	public Node getTop() {
		return top;
	}

	// 判断栈满
	public boolean isFull() {
		return count == maxSize;
	}

	// 入栈
	public void pushNode(Node node) {

		if (isFull()) {
			System.out.println("栈满");
			return;
		}

		top.next = node;// 如果栈不满则将当前的栈顶节点指向新增节点
		top = node;// 新增节点成为新的栈顶节点
		count++;// 当前栈容量加1

	}

	public void popNode() {
		if (head.next == null) {
			System.out.println("栈空");
			return;
		}

		Node helper = head;// 定义了一个辅助节点
		while (true) {
			if (helper.next == top) {// 当辅助节点指向栈顶节点的前一个是条件成立
				System.out.println("当前栈顶节点是:" + helper.next);
				helper.next = null;// 辅助节点指向空 原先的栈顶节点因为没有引用被回收
				top = helper;// 当前辅助节点的成为了新的栈顶节点
				count--;// 当前栈的容量-1
				break;
			}
			helper = helper.next;
		}

	}

//	//方法一:利用栈这个数据结构,将各个节点压入栈中,然后利用栈的先进后出的特点,实现逆序打印效果
//	 public  void list1(Node head) {
//		 if(head.next == null) {
//			 return;//空链表 不能打印
//		 }
//		 Stack<Node> stack = new Stack<Node>();
//		 Node cur = head.next;
//		 //将链表的所有节点压入栈中
//		 while(cur != null) {
//			 stack.push(cur);
//			 cur = cur.next;
//		 }
//		 //将栈中节点打印
//		 while(stack.size() > 0) {
//			 System.out.println(stack.pop());
//		 }
//	 }

	// 方法二:将单链表两次反转 实现逆序打印和恢复的效果
	public void reverseList(Node head) {
		// 如果为空
		if (head.next == null || head.next.next == null) {// 如果链表为空或只有一个节点 那么无需处理
			return;
		}
		Node cur = head.next;
		Node next = null;
		Node reverseHead = new Node(0);
		// 遍历原来的链表 每遍历一个节点就将其取出 并放在新的reversehead 的最前端
		while (cur != null) {
			next = cur.next;// 先保留cur的下一个节点,因为后面需要使用
			cur.next = reverseHead.next;// 将cur的下一个节点指向新的链表的最前端
			reverseHead.next = cur;
			cur = next; // cur后移

		}
		// 将head.next指向reverseHead.next
		head.next = reverseHead.next;
	}

	public void list2(Node head) {
		if (head.next == null) {
			System.out.println("链空");
			return;
		}
		reverseList(head);
		Node helper = head.next;
		while (helper != null) {
			System.out.println(helper);
			helper = helper.next;
		}
		reverseList(head);
	}

}

class Node {

	public int no;// 编号
	public Node next;// 指向下一个节点

	public Node(int no) {
		this.no = no;

	}

	// 为了显示方便重写toString方法
	public String toString() {
		return "Node [no=" + no + "]";
	}

}