数据结构——栈的基本总结

最近刷数据结构的黑宝书,顺便将数据结构进行下总结,就先从最熟悉的栈开始吧。


栈(stack),数据结构中的一种,准确的来说,应该是数据逻辑结构

栈的基本特点为: 后进先出,就像生活中我们取放盘子,当一摞盘子在桌子上时候,我们总是会取最上边的盘子,同时,我们在放盘子时,也会放在最上面。同样这种机制也在我们浏览网页时也有出现,在我们浏览网页时,左上角的转到上一页就是这种,最近浏览的网站在最上层,当返回时,先取到最上层的地址,这样即实现了逐层后退。

栈有几个基本的操作

  • push         向栈底添加一个元素     
  • pop           从栈顶取出一个元素
  • peek          复制栈顶元素,但不进行删除
  • size           判定栈中所含元素的个数
  • isEmpty    判断栈是否为空

因为对树结构还不够熟悉,我们就用简单的数组链表来实现一个栈。


数组实现

利用数组实现栈,我们可以设置自定义容量和默认容量,也可以设置自动扩容机制。数组实现机制相对来说更加简单,考虑到栈的操作总是取最近添加的元素,所以,我们以头部作为栈底,尾部作为栈顶,这样向栈内添加元素时,时间复杂度为常数,对于经常对栈顶进行操作,并且栈内数据非常庞大的情况下,效率相对较高。

下面利用Java代码进行方法实现

package Stack;

public class ArrayStack {
	/*
	 * 该类为使用数组实现的一个栈(Stack)
	 * 具有成员方法pop,push,peek,isEmpty,size,getMaxElementNumber
	 * 具有构造方法两种,默认容量和指定容量
	 * 数组应具有自动扩容能力(可选)
	 */
	//该值为栈索引,各项方法均对其进行操作(固定长度数组)
	private int STACK_ARRAY_INDEX_OF_HANDMOVEMENT = 0;
	//该值为栈最大容量数
	public int TOP;
	
	private Object[] StackArray;
	
	public ArrayStack() {
		//默认栈容量为15
		StackArray = new Object[15];
	}
	
	public ArrayStack(int TOP) {
		//指定栈容量
		StackArray = new Object[TOP];
		//返回TOP值,用于后续判断操作
		this.TOP = TOP;
	}
	/*
	 * 栈推入操作  具有判满功能
	 */
	public boolean push(Object element) {
		//判断栈顶是否满元素,若满,进行扩容,若空进行添加
		if(StackArray[StackArray.length-1] != null) {
			/*
			 * 准备新数组,将原数组数据全部复制进去
			 * 将原数组删除并扩容 扩容指数为2倍
			 * 将新数组数据复制进原数组
			 */
			Object[] StackArrayNew = new Object[StackArray.length];
			for(int i = 0;i<=StackArrayNew.length;i++) {
				StackArrayNew[i] = StackArray[i];
			}
			StackArray = new Object[StackArrayNew.length * 2];
			for(int i = 0;i<=StackArrayNew.length;i++) {
				StackArray[i] = StackArrayNew[i];
			}
			StackArray[STACK_ARRAY_INDEX_OF_HANDMOVEMENT] = element;
			STACK_ARRAY_INDEX_OF_HANDMOVEMENT++;
			return true;
		}else {
			StackArray[STACK_ARRAY_INDEX_OF_HANDMOVEMENT] = element;
			STACK_ARRAY_INDEX_OF_HANDMOVEMENT++;
			return true;
		}
	}
	
	/*
	 * 栈取出操作,具有判空功能
	 */
	public Object pop() {
		//判断栈中是否有元素,若有返回Object实例,若无返回提示
		
		if(StackArray[0] == null) {
			return null;
		}else {
			Object theReturnResult =                                                
StackArray[STACK_ARRAY_INDEX_OF_HANDMOVEMENT];
			StackArray[STACK_ARRAY_INDEX_OF_HANDMOVEMENT] = null;
			return theReturnResult;
		}
	}
	/*
	 * 判断栈中元素个数方法
	 */
	public int size() {
		int index = 0;
		while(StackArray[index] == null) {
			index++;
		}
		return index;  
	}
	/*
	 * 判断是否为空
	 */
	public boolean isEmpty() {
		if(StackArray[0] == null) 
			return true;
			return false;
	}
	/*
	 * peek复制栈顶元素
	 */
	public Object peek() {
		//判断栈中是否有元素,若有返回Object实例,若无返回提示
		if(StackArray[0] == null) {
			System.out.println("该栈为空");
			return null;
		}else {
			Object theReturnResult = StackArray[STACK_ARRAY_INDEX_OF_HANDMOVEMENT];
			return theReturnResult;
		}
	}
}

Ps:该栈内实现了基本的五个操作,并且对基本的操作进行了判空功能。


链表实现

在这里就先不进行链表的介绍,等有时间再开一篇链表的总结。

为了实现起来更加方便,利用单链表即可满足栈的需求。对于链表来说,增删改的操作时间为常数,而因为其引用的特性,遍历的花费十分昂贵,所以我们为了优化栈的性能,尽可能减少遍历链表所浪费的时间,我们将链表表头作为栈顶,这样每次存取操作只需要用头引用取表头数据即可。

首先我们需要在链表内维护一个节点类

package MyLinkedList;
/*
 * 该类为单链表类的节点类,该类只服务于LinkedList类,并不进行对外暴露
 */
public class SingleLinkedListNode {
	//该引用为链表中的数据部分,用于存放数据
	public Object data;
	//该引用为指向下一个链表,最后一个可循环或者置空
	public SingleLinkedListNode Next;
	
	public SingleLinkedListNode(Object data,SingleLinkedListNode Next) {
		this.data = data;
		this.Next = Next;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}

	public SingleLinkedListNode getNext() {
		return Next;
	}

	public void setNext(SingleLinkedListNode next) {
		Next = next;
	}
	
}

下面用链表实现

package MyLinkedList;
/*
 * 该类为单链表类的节点类,该类只服务于LinkedList类,并不进行对外暴露
 */
public class SingleLinkedListNode {
	//该引用为链表中的数据部分,用于存放数据
	public Object data;
	//该引用为指向下一个链表,最后一个可循环或者置空
	public SingleLinkedListNode Next;
	
	public SingleLinkedListNode(Object data,SingleLinkedListNode Next) {
		this.data = data;
		this.Next = Next;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}

	public SingleLinkedListNode getNext() {
		return Next;
	}

	public void setNext(SingleLinkedListNode next) {
		Next = next;
	}
}

只实现了几个基本操作,对于size,isEmpty等方法,和数组实现原理相同。


最后再简单介绍一种较为特殊的栈,该栈为栈中的一个特殊形式,主要用于取消操作,使用数组进行实现,该栈不能进行自动扩容,并且栈满后将从栈低进行元素删除。

其原理和以上两种栈无差别,只不过在栈满后,先将栈底元素删除,再将栈元素向前移动,最后在栈顶添加元素。

package Stack;

public class OverFlowStack {
	/*
	 * 该栈为栈中的一个特殊形式,主要用于取消操作,使用数组进行实现 
	 * 该栈不能进行自动扩容,并且栈满后将从栈低进行元素删除
	 * 该栈具有方法为pop,push,peek,size,isEmpty
	 */

	// 该值为栈索引,各项方法均对其进行操作(固定长度数组)
	private int STACK_ARRAY_INDEX_OF_HANDMOVEMENT = 0;

	public int TOP;

	private Object[] OverFlowStack;

	public OverFlowStack() {
		// 默认栈容量为15
		OverFlowStack = new Object[15];
	}

	public OverFlowStack(int TOP) {
		// 指定栈容量
		OverFlowStack = new Object[TOP];
		// 返回TOP值,用于后续判断操作
		this.TOP = TOP;
	}

	public boolean push(Object element) {
		// 首先对栈进行数据判断,如果栈内还有空间,直接添加
		// 如果栈内已经满数据,从栈底删除最后一个数据并进行数组索引的移动
		if (OverFlowStack[OverFlowStack.length - 1] == null) {
			OverFlowStack[STACK_ARRAY_INDEX_OF_HANDMOVEMENT] = element;
			return true;
		} else {
			// 通过while进行对栈内数据移动的操作
			// 移动次数为INDEX-1
			int temp = 0;
			while (temp <= OverFlowStack.length - 1) {
				OverFlowStack[temp] = OverFlowStack[temp + 1];
				temp++;
			}
			return true;
		}
	}
	/*
	 * 栈取出操作,具有判空功能
	 */
	public Object pop() {
		//判断栈中是否有元素,若有返回Object实例,若无返回提示
		
		if(OverFlowStack[0] == null) {
			return null;
		}else {
			Object theReturnResult = OverFlowStack[STACK_ARRAY_INDEX_OF_HANDMOVEMENT];
			OverFlowStack[STACK_ARRAY_INDEX_OF_HANDMOVEMENT] = null;
			return theReturnResult;
		}
	}
	/*
	 * 判断栈中元素个数方法
	 */
	public int size() {
		int index = 0;
		while(OverFlowStack[index] == null) {
			index++;
		}
		return index;  
	}
	/*
	 * 判断是否为空
	 */
	public boolean isEmpty() {
		if(OverFlowStack[0] == null) 
			return true;
			return false;
	}
	/*
	 * peek复制栈顶元素
	 */
	public Object peek() {
		//判断栈中是否有元素,若有返回Object实例,若无返回提示
		if(OverFlowStack[0] == null) {
			System.out.println("该栈为空");
			return null;
		}else {
			Object theReturnResult = OverFlowStack[STACK_ARRAY_INDEX_OF_HANDMOVEMENT];
			return theReturnResult;
		}
	}
}

基本内容就总结到这里,如果有错误的地方请留言指出,萌新发文,请大神轻喷。

本文原创,转载请注明来源。

QQ   489282384

                         JoryB

猜你喜欢

转载自blog.csdn.net/weixin_41582192/article/details/81170232