日撸Java三百行(day14:栈)

目录

一、栈的基本知识

1.栈的概念

2.栈的功能

3.栈的实现

二、栈的代码实现

1.栈的基本属性与方法

2.栈的遍历

3.入栈实现

4.出栈实现

5.数据测试

6.完整的程序代码

总结


一、栈的基本知识

1.栈的概念

根据百度百科,我们知道“”是存储货物或供旅客住宿的地方,可引申为仓库、中转站,所以引入到计算机领域里,栈就是数据暂时存储的地方,当栈中没有数据元素时叫做空栈。

栈(stack),是一种运算受限的线性表,限定只在表尾进行插入和删除操作,插入删除这一端就叫栈顶,另一端就叫栈底,总结一下就是“栈底固定,栈顶浮动”。

而正因为栈运算受限,只能在栈顶进行插入删除操作,所以栈是一种先进后出(后进先出)的数据结构。

2.栈的功能

栈的主要功能有push(入栈)、pop(出栈)、peek(获取栈顶元素,但不删除)、empty(判断栈是否为空)等,这里我们重点讨论入栈和出栈。

入栈:即向一个栈插入新元素,把新元素放到原栈顶元素的上面,使之成为新的栈顶元素。

出栈:即从一个栈中删除元素,把原栈顶元素删除,使其相邻的元素成为新的栈顶元素。

为了更好地理解栈的基本概念与入栈出栈,下面用图进行说明:

3.栈的实现

因为栈存储的是相同类型的数据,所以栈的实现有两种,一种是顺序栈,底层为数组;另一种是链式栈,利用链表实现。今天我们主要通过数组(顺序表)来完成栈的实现。

二、栈的代码实现

1.栈的基本属性与方法

有了前几天顺序表和链表的相关基础,创建栈的基本属性和方法就可以很快完成,代码如下:

public class CharStack {
	/**
	 * The depth.
	 */
	public static final int MAX_DEPTH = 10;
	
	/**
	 * The actual depth.
	 */
	int depth;
	
	/**
	 * The data.
	 */
	char[] data;
	
	/**
	 *********************
	 * Construct an empty char stack.
	 *********************
	 */
	public CharStack() {
		depth = 0;
		data = new char[MAX_DEPTH];
	} // of the first constructor

这里我们同样利用final关键字来定义栈的最大长度MAX_DEPTH = 10,然后定义成员变量(depth、data),再利用new关键字为data分配内存空间。

2.栈的遍历

栈的遍历同样可以通过重写toString()方法来实现,大体结构上与顺序表、链表差不多,只是循环的时候,要注意由于栈是在栈顶这一端进行插入删除操作,所以为了便于后续入栈和出栈,我们将栈顶端对应数组的最右端(下标最大处),代码如下:

    /**
	 *********************
	 * Overrides the method claimed in Object, the superclass of any class.
	 *********************
	 */
	public String toString() {
		String resultString = "";
		
		for (int i = 0; i < depth; i++) {
			resultString += data[i];
		} // of for i
		
		return resultString;
	} // of toString

3.入栈实现

和顺序表、链表一样,在入栈之前,我们显然需要先考虑此栈是否已满,对于这个问题,一样的套路,直接利用if语句进行判断:

  • 如果此时栈的长度depth = MAX_DEPTH,那么就输出Stack full.,提示此栈已满。
  • 如果此时栈的长度未达到MAX_DEPTH,说明栈还未满,直接将插入元素令为新的栈顶元素即可完成入栈。我们知道在插入前,原栈顶元素的下标为depth - 1(因为栈底从0开始索引),那么显然新栈顶元素的下标应在此基础上加1,所以data[depth] = paraChar;,最后不要忘了把栈的实际长度depth增加1(因为插入了一个新元素)。
    /**
	 *********************
	 * Push an element.
	 * 
	 * @param paraChar The given char.
	 * @return Success or not.
	 *********************
	 */
	public boolean push(char paraChar) {
		if (depth == MAX_DEPTH) {
			System.out.println("Stack full.");
			return false;
		} // of if
		
		data[depth] = paraChar;
		depth++;
		
		return true;
	} // of push

4.出栈实现

顺序表、链表执行删除操作之前需要先判断是否为空表,类似的,在执行出栈操作之前,也需要先判断栈是否为空,这里仍然用的是if语句进行判断,并将'\0'作为返回值。

出栈其实就是删除栈顶元素,也就是删除栈最上面的元素(数组最右边的元素),所以直接将栈的长度depth减少1即可,不过,在此之前还是需要将要删除的栈顶元素赋给resultChar并返回。

    /**
	 *********************
	 * Pop an element.
	 * 
	 * @return The popped char.
	 *********************
	 */
	public char pop() {
		if(depth == 0) {
			System.out.println("Nothing to pop.");
			return '\0';
		} // of if
		
		char resultChar = data[depth - 1];
		depth--;
		
		return resultChar;
	} // of pop

5.数据测试

接下来我们照例进行数据测试:

    /**
	 *********************
	 *The entrance of the program.
	 *
	 * @param args Not used now.
	 *********************
	 */
	public static void main(String[] args) {
		CharStack tempStack = new CharStack();
		
		for(char ch = 'a'; ch < 'm'; ch++) {
			tempStack.push(ch);
			System.out.println("The current stack is: " + tempStack);
		} // of for ch
		
		char tempChar;
		for(int i = 0; i < 12; i++) {
			tempChar = tempStack.pop();
			System.out.println("Popped: " + tempChar);
			System.out.println("The current stack is: " + tempStack);
		} // of for i
	} // of main

6.完整的程序代码

package datastructure;

/**
 *Char stack. I do not use Stack because it is already defined in Java.
 *
 *@auther Xin Lin 3101540094@qq.com.
 */

public class CharStack {
	/**
	 * The depth.
	 */
	public static final int MAX_DEPTH = 10;
	
	/**
	 * The actual depth.
	 */
	int depth;
	
	/**
	 * The data.
	 */
	char[] data;
	
	/**
	 *********************
	 * Construct an empty char stack.
	 *********************
	 */
	public CharStack() {
		depth = 0;
		data = new char[MAX_DEPTH];
	} // of the first constructor
	
	/**
	 *********************
	 * Overrides the method claimed in Object, the superclass of any class.
	 *********************
	 */
	public String toString() {
		String resultString = "";
		
		for (int i = 0; i < depth; i++) {
			resultString += data[i];
		} // of for i
		
		return resultString;
	} // of toString
	
	/**
	 *********************
	 * Push an element.
	 * 
	 * @param paraChar The given char.
	 * @return Success or not.
	 *********************
	 */
	public boolean push(char paraChar) {
		if (depth == MAX_DEPTH) {
			System.out.println("Stack full.");
			return false;
		} // of if
		
		data[depth] = paraChar;
		depth++;
		
		return true;
	} // of push
	
	/**
	 *********************
	 * Pop an element.
	 * 
	 * @return The popped char.
	 *********************
	 */
	public char pop() {
		if(depth == 0) {
			System.out.println("Nothing to pop.");
			return '\0';
		} // of if
		
		char resultChar = data[depth - 1];
		depth--;
		
		return resultChar;
	} // of pop
	
	/**
	 *********************
	 *The entrance of the program.
	 *
	 * @param args Not used now.
	 *********************
	 */
	public static void main(String[] args) {
		CharStack tempStack = new CharStack();
		
		for(char ch = 'a'; ch < 'm'; ch++) {
			tempStack.push(ch);
			System.out.println("The current stack is: " + tempStack);
		} // of for ch
		
		char tempChar;
		for(int i = 0; i < 12; i++) {
			tempChar = tempStack.pop();
			System.out.println("Popped: " + tempChar);
			System.out.println("The current stack is: " + tempStack);
		} // of for i
	} // of main
} // of class CharStack

运行结果:

入栈时:测试的数据是从'a'到'm'之前(即从'a'到'l'这12个数据元素) ,但是在程序最开始我们就已经规定了栈的最大长度为10,所以不用说,当执行入栈操作时,最后'k'、'l'这两个数据元素必然没办法完成入栈。

出栈时:我们设置了for循环的次数为12次,即需要执行12次出栈操作,但是此时栈中只有'a'~'j'这10个数据元素,所以最后两次出栈时Nothing to pop.

总结

总的来说,今天的代码还是比较容易的,一方面是因为有了前两天顺序表和链表的基础,另一方面是因为栈的操作本身就不复杂,而且入栈出栈的时间复杂度均为O(1),所以利用栈来存取数据是比较迅速的。不过,栈虽然操作不复杂,但是它在计算机领域却有着举足轻重的作用,栈不仅是一种高效的内存结构,还贡献于计算机底层技术(例如函数调用、中断处理、程序调试等)。

  • 24
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值