本文共 5826 字,大约阅读时间需要 19 分钟。
栈(stack)是限制对元素的插入(push)和删除(pop)只能在一个位置上进行的表,该位置是表的末端,叫做栈的栈顶(top)。
栈的基本操作只有两种,压入栈(push)和弹出栈顶(pop),且只能作用于栈顶。(只有栈顶元素是可访问的
你可以把栈结构理解成一个底部封闭,顶部打开的桶。最先进去的元素一定是最后才能取出,最晚进去的元素一定是最先取出。
因此栈又叫做LIFO(后进先出,Last In First Out)表。栈的操作是常数时间的,而且是以非常快的常数时间。在某些机器上,push和pop都可以写成一条机器指令,现代计算机把栈操作作为它指令的一部分。因此栈是在计算机科学中继数组之后最基本的数据结构。
栈的实现分为数组实现和链表实现。
1public class StackImplementByLinklist{ 2 public Node first; 3 int size; 4 //内部类定义node 5 public class Node { 6 AnyType data; 7 Node next; 8 } 9 //初始化 10 public void stack(){ 11 first=null; 12 size=0; 13 } 14 15 public void push(AnyType a){ 16 Node oldNode=first; 17 first=new Node(); 18 first.data=a; 19 first.next=oldNode; 20 size++; 21 } 22 23 public AnyType pop(){ 24 AnyType a=first.data; 25 first=first.next; 26 size--; 27 return a; 28 } 29 30 public boolean isEmpty(){ 31 return size==0; 32 } 33 34 public int size(){ 35 return size; 36 } 37}
1public class StackImplementByArray{ 2 AnyType[] arr; 3 int size; 4 public void stack(int capacity){ 5 arr=(AnyType[])new Object[capacity]; 6 size=0; 7 } 8 public void push(AnyType a){ 9 if(size==arr.length){ 10 changeArray(2*size+1); 11 } 12 arr[size]=a; 13 size++; 14 } 15 public AnyType pop(){ 16 if(size==0){ 17 System.out.println("栈顶为空"); 18 System.exit(0); 19 } 20 AnyType a=arr[size-1]; 21 arr[size-1]=null; 22 size--; 23 return a; 24 } 25 public boolean isEmpty(){ 26 return size==0; 27 } 28 public int size(){ 29 return size; 30 } 31 32 //由于数组大小是要先确定的,因此当数组满了后要扩大数组容量 33 public void changeArray(int newCapacity){ 34 AnyType[] newArr=(AnyType[])new Object[newCapacity]; 35 for(int i=0;i
编译器检查程序符号的语法错误,常常就是通过栈来实现的。
在编程时,我们经常会用到“ ( ),[ ],{ }," " ”这些符号,当这些符号不是配对出现的,编译器就会报错,编译就无法通过。
那么,编译器是怎么知道这些符号有没有配对出现的呢?它通常是这么处理的。
当遇到左符号,如“( [ { " ”这些,就把它压入一个准备好的栈;否则就弹出栈顶,检测当前符号是否与栈顶元素配对。一旦不能配对,直接退出报错。
wiki: 队列,又称为伫列(queue),是先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为rear)进行插入操作,在前端(称为front)进行删除操作。队列的操作方式和堆栈类似,唯一的区别在于队列只允许新数据在后端进行添加。
队列模型就相当于我们日常生活的排队,在队伍的后面入队,在队伍的前端出队。
队列一般分为普通的数组队列,链表队列和循环队列。
链表队列:长度一般是无限的,一般不存在溢出的可能性,用完就销毁,不会浪费内存空间。
普通的数组队列:长度一般是有限的,即数组长度。由于元素出队后其位置的内存空间并不会释放,因此会浪费大量的内存空间。
循环队列:特殊的数组队列,由于普通的数组的队列会浪费大量的内存空间,因此出现了循环队列。当循环队列的队尾指针到达数组末尾后,会重新回到数组起始位置,实现了对内存的重复利用。
1.链表队列
1public class QueueImplementByLinkList{ 2 Node first;//队首 3 Node last;//队尾 4 int size; 5 public class Node{ 6 AnyType data; 7 Node next; 8 public Node(AnyType data,Node next){ 9 this.data=data; 10 this.next=next; 11 } 12 } 13 14 //初始化队列 15 public void initqueue(){ 16 first=new Node(null,null); 17 last=first; 18 size=0; 19 } 20 21 //入队 22 public void enqueue(AnyType a){ 23 if(size==0){ 24 last.data=a; 25 size++; 26 return; 27 } 28 Node oldlast=last; 29 last=new Node(a,null); 30 oldlast.next=last; 31 size++; 32 } 33 34 //出队 35 public AnyType dequeue(){ 36 if(size==0){ 37 System.out.print("队列为空"); 38 System.exit(0); 39 } 40 AnyType a=first.data; 41 first=first.next; 42 size--; 43 return a; 44 } 45 public boolean isEmpty(){ 46 return size==0; 47 } 48 public int size(){ 49 return size; 50 } 51}
2.数组队列
1public class QueueImplementByArray{ 2 AnyType[] arr; 3 int first; 4 int last; 5 int size; 6 //初始化 7 public void ininqueue(int capacity){ 8 arr=(AnyType[])new Object[capacity]; 9 first=0; 10 last=0; 11 size=0; 12 } 13 public void enqueue(AnyType a){ 14 if(size==arr.length){ 15 changeArray(2*size+1); 16 } 17 arr[last++]=a; 18 size++; 19 } 20 public AnyType dequeue(){ 21 if(size==0){ 22 System.out.println("队列为空"); 23 System.exit(0); 24 } 25 AnyType a=arr[first++]; 26 arr[first-1]=null; 27 size--; 28 return a; 29 } 30 public void changeArray(int newCapacity){ 31 AnyType[] newArr=(AnyType[])new Object[newCapacity]; 32 for(int i=0;i
1public class CycleQueue { 2 int[] arr; 3 int start;//队首 4 int end;//队尾 5 int size=0; 6 //初始化 7 public void initqueue(int size){ 8 arr=new int[size]; 9 size=0; 10 start=0; 11 end=0; 12 } 13 14 //入队 15 public void enqueue(int num){ 16 if(size>arr.length){ 17 System.out.println("队列已满"); 18 return; 19 } 20 if(end==arr.length){ 21 end=0; 22 } 23 arr[end++]=num; 24 size++; 25 } 26 27 //出队 28 public int dequeue(){ 29 if(size==0){ 30 System.out.println("队列为空"); 31 System.exit(0); 32 } 33 if(start==arr.length){ 34 start=0; 35 } 36 size--; 37 return arr[start++]; 38 } 39 40 public boolean isEmpty(){ 41 return size==0; 42 } 43 public int size(){ 44 return size; 45 } 46}
栈和队列是基本的数据结构,是对数组和链表的重新封装和扩展。由于它们的特性和执行速度,栈和队列被广泛的使用。
最后,不要为了使用数据结构而使用使用数据结构,要区分各种数据结构的使用场景,灵活地运用数据结构,可以事半功倍。
如果这篇文章对你有帮助的话,左下角给个推荐鸭,这个对我真的很重要?!
转载地址:http://cfjfz.baihongyu.com/