【数据结构】堆栈(顺序栈、链式栈)

一、栈的定义

1、术语:

栈(stack):是一种只允许在表的一端进行插入或删除操作的线性表。

栈顶:表尾端,即表中允许进行插入和删除操作的一端称为栈顶。栈顶是动态的,它由一个称为栈顶指针的位置指示器指示。

栈底:表头端,即栈的最下面的那一端称为栈底。

空栈:没有元素的栈

进栈或入栈:堆栈的插入操作

出栈或退栈:堆栈的删除操作

2、栈的特点:

        “后进先出”,因此,栈又被称为后进先出(last in first out,LIFO)表。它的实现方式主要有顺序栈、链栈两种。

3、栈的抽象数据类型:

        数据元素:可以是任意类型,用泛型表示

        数据关系:数据元素建是线性关系

        数据操作:入栈、出栈、取栈顶元素、返回栈中元素个数、判断栈是否为空

       我们定义抽象数据类型如下:

package codingTest2;

public interface IStack {
	E push(E item);//入栈
	E pop();//出栈
	E peek();//取栈顶元素
	int size();//返回栈中元素个数
	boolean empty();//判断栈是否为空
}

二、顺序栈

1、定义:

       顺序栈是利用顺序存储结构实现的栈,即利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。

       类似于顺序表,它使用一维数组来存放顺序栈中的数据元素。

       栈顶指示器top设在数组下标为最大的那一端,top随着插入或删除而变化。

       当栈为空时,top=-1;其他时候,top为栈顶元素的索引号。

2、特点:

      优点:相比于链栈,顺序栈在实现以及操作上均比链栈要容易许多 

      缺点:相比链栈,顺序栈只能在事先进行预申请,所以在存放较大数据量的数据时会存在栈满或则说时栈溢出的情况,在用顺序栈时需提前注意。

import java.lang.reflect.Array;

//用数组实现顺序栈
class arraysSequentialStack {
	public class SeqStack implements IStack{
		private int maxSize;
		private E[] data;
		private int top;
		
		//初始化栈
		public SeqStack(Class type, int size) {
			data = (E[])Array.newInstance(type, size);//初始化一个类型为type,大小为size的数组
			maxSize = size;//容量最大为size
			top = -1;
		}

		@Override
		//将数据压入栈中
		public E push(E item) {
			if(!isFull()) {
				data[++top] = item;
				return item;
			}else {
				return null;
			}
		}

		private boolean isFull() {
			if(top == maxSize - 1) {
				return true;
			}else {
				return false;
			}
		}

		//元素出栈
		@Override
		public E pop() {
			E item = null;
			if(!empty()) {
				item = data[top--];
			}
			return item;
		}

		@Override
		//取栈顶元素
		public E peek() {
			E item = null;
			if(!empty()) {
				return data[top];
			}
			return item;
		}

		@Override
		//返回元素的大小
		public int size() {
			return top + 1;
		}

		@Override
		//判断顺序栈是否为空
		public boolean empty() {
			if(top == -1) {
				return true;
			}else {
				return false;
			}
		}
		
	}
}

 

 

三、链式栈

1、定义:

       采用链式存储结构实现的栈,通常用单链表来表示链栈。

       它的结点结构与单链表的结构一样,都是由数据域data和引用域next两部分组成。

       由于链栈的操作只在一段进行(栈顶),为了操作方便,我们将栈顶设在链表的头部,即将栈顶指示器指向链表的头部,所有对栈的数据元素的增加和删除操作都在链表头部进行。

2、特点:

          优点:相比于顺序栈,链栈在计算机内存允许的情况下可以存放不限个数的数据单元,也无需考虑栈满的情况

          缺点:相比顺序栈,链栈在实现过程中较为复杂一些

package codingTest2;

public class StackNode{
	private E data;
	private StackNode next;
	
	public StackNode(){}
	
	public StackNode(E data) {
		this.data = data;
	}
	
	public StackNode(E data, StackNode next) {
		this.data = data;
		this.next = next;
	}
	
	public E getData() {
		return data;
	}
	
	public void setData(E data) {
		this.data = data;
	}
	
	public StackNode getNext() {
		return next;
	}
	
	public void setNext(StackNode next) {
		this.next = next;
	}
}
package codingTest2;

public class arraysLinkedStack implements IStack{
	private StackNode top;//栈顶指示器
	private int size;//栈中节点个数
	
	//初始化栈
	public void LinkStack() {
		top = null;
		size = 0;
	}

	//将数据压入栈中
	@Override
	public E push(E item) {
		StackNode newNode = new StackNode(item);
		if(!empty()) {
			newNode.setNext(top);
		}
		top = newNode;
		++size;
		
		return item;
	}

	//出栈操作
	@Override
	public E pop() {
		E item = null;
		if(!empty()) {
			item = top.getData();
			top = top.getNext();
			size --;
		}
		return item;
	}

	//取栈顶元素
	@Override
	public E peek() {
		E item = null;
		if(!empty()) {
			item = top.getData();
		}
		return item;
	}
	
	//求栈的长度
	@Override
	public int size() {
		return size;
	}

	//判断栈是否为空
	@Override
	public boolean empty() {
		if((top == null) && (size == 0)) {
			return true;
		}else {
			return false;
		}
	}
	
}

三、leetcode习题

有效的括号

给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。

注意空字符串可被认为是有效字符串。

示例 1:

输入: "()"
输出: true

示例 2:

输入: "()[]{}"
输出: true

示例 3:

输入: "(]"
输出: false

示例 4:

输入: "([)]"
输出: false

示例 5:

输入: "{[]}"
输出: true
package codingTest2;

import java.util.Stack;

public class ValidParentheses {
	public static boolean isValid(String str) {
		//将字符串转换为字符数组
		char[] chs = str.toCharArray();
		Stack s= new Stack<>();
		//对于字符数组中的每一个字符元素有;
		for(char ch : chs) {
			if(ch == '(' || ch == '[' || ch == '{') {
				s.push(ch);
			}else {
				if(s.size() == 0) {
					return false;
				}
				if(ch == '}' && s.peek() == '{') {
					s.pop();
				}else if(ch == ')' && s.peek() == '(') {
					s.pop();
				}else if(ch == ']' && s.peek() == '[') {
					s.pop();
				}else {
					return false;
				}
			}
		}
		return s.size() == 0;

	}
	
	public static void main(String[] args) {
		System.out.println(isValid("[][]"));
		System.out.println(isValid("[]["));
	}
}

 

四、队列

https://blog.csdn.net/volcano1995/article/details/88092631

五、递归

https://blog.csdn.net/volcano1995/article/details/88090188

 

参考文献 

本文主要参考了以下两篇文章:

https://blog.csdn.net/qq_38410730/article/details/79587711
https://blog.csdn.net/qq_36441169/article/details/80760372 

 


 

你可能感兴趣的:(Java学习笔记,数据结构与算法)