日常学习随笔-数组单链表双链表三种形式实现栈结构的基本操作

Posted 小风微灵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了日常学习随笔-数组单链表双链表三种形式实现栈结构的基本操作相关的知识,希望对你有一定的参考价值。

一、栈结构

  栈(stack)是限制插入和删除只能在一个位置上的表,该位置是 表的末端,叫做栈的顶(Top)。对栈的基本操作有push(进栈),pop(出栈),peak(栈顶元素),size(栈容量)等。

  栈的核心思想:“先进后出”。

二、案例一:数组实现“栈”  

  1 package com.xfwl.algorithmAnalysis.stack;
  2 
  3 import java.util.Arrays;
  4 
  5 /**
  6  * 自定义栈结构(基于数组的形式)
  7  * 栈的核心思想:先进后出
  8  * @function  日常学习测试
  9  * @author 小风微凉
 10  * @time  2018-5-19 上午10:19:07
 11  * @param <T>
 12  */
 13 public class MyStackDefin3<T> {
 14     /**
 15      * 定义一个默认扩展容量
 16      */
 17     private static final int DEFAULT_CAPACITY=10;
 18     /**
 19      * 栈-容器数组
 20      */
 21     private T[] stackArr;
 22     /**
 23      * 计数器
 24      */
 25     private int nodeCount=0;
 26     /**
 27      * 设置容器大小
 28      * @param newCapacity 新容量大小
 29      * 说明:这里参考ArrayList源码中的一套扩展规则">>"
 30      */
 31     public void ensureCapacity(int newCapacity){
 32         //大小范围检查
 33         if(newCapacity<=this.size()){//不超过了当前容器的容量大小
 34             return;//则不需要扩展容器容量
 35         }
 36         //数组初始值判断 
 37         if(this.stackArr==null){
 38             stackArr=(T[]) new Object[newCapacity];
 39             return;//第一次初始化进来
 40         }
 41         //需要扩展容器容量
 42         T[] newItems=(T[]) Arrays.copyOf(this.stackArr, newCapacity,this.stackArr.getClass());
 43         this.stackArr=newItems;
 44     }
 45     /**
 46      * 栈构造器
 47      */
 48     public MyStackDefin3(){
 49         //重置栈结构
 50         this.ensureCapacity(DEFAULT_CAPACITY);
 51         nodeCount=0;
 52     }    
 53     /**
 54      * 数据入栈
 55      * @param data
 56      */
 57     public void push(T data){
 58         if(this.size()==this.stackArr.length){//数组容量达到上限
 59             int newCapacity=this.size()+this.size()>>1;//扩展量:取当前容量的一半,且向下取整
 60             this.ensureCapacity(newCapacity);
 61         }
 62         this.stackArr[this.size()]=data;    
 63         this.nodeCount++;
 64     }
 65     /**
 66      * 数据出栈
 67      */
 68     public void pop(){
 69         this.stackArr[this.size()-1]=null;    
 70         this.nodeCount--;        
 71     }
 72     /**
 73      * 返回当前栈中的数据条数
 74      * @return
 75      */
 76     public int size(){
 77         return this.nodeCount;
 78     }
 79     
 80     /**
 81      * 返回栈的最顶端的元素
 82      * @return
 83      */
 84     public T peak(){
 85         return this.stackArr[(this.size()-1)<0?0:this.size()-1];
 86     }
 87     /**
 88      * 打印当前栈信息
 89      */
 90     public void print(){
 91         System.out.println("----------开始打印----------------------");
 92         if(this.size()==0){
 93             System.out.println("空栈,无检索数据!");
 94         }else{            
 95             for(int i=0;i<this.size();i++){
 96                 System.out.println("栈结点数据:"+this.stackArr[i]);                
 97             }
 98         }        
 99         System.out.println("----------打印结束----------------------");
100     }
101 }

测试类:

 1 package com.xfwl.algorithmAnalysis.stack;
 2 /**
 3  * 测试类
 4  * @function  
 5  * @author 小风微凉
 6  * @time  2018-5-19 上午9:43:05
 7  */
 8 public class Test3 {
 9     public static void main(String[] args) {
10         //创建一个空栈
11         MyStackDefin3<Object> stack=new MyStackDefin3<>();
12         stack.print();
13         System.out.println("当前栈顶数据:"+stack.peak());
14         //数据入栈
15         stack.push("第1个数据");
16         stack.push("第2个数据");
17         stack.push("第3个数据");
18         stack.push("第4个数据");
19         stack.push("第5个数据");
20         //打印
21         stack.print();
22         System.out.println("当前栈顶数据:"+stack.peak());
23         //数据出栈
24         stack.pop();
25         //打印
26         stack.print();
27         System.out.println("当前栈顶数据:"+stack.peak());
28     }
29 }

运行结果:

----------开始打印----------------------
空栈,无检索数据!
----------打印结束----------------------
当前栈顶数据:null
----------开始打印----------------------
栈结点数据:第1个数据
栈结点数据:第2个数据
栈结点数据:第3个数据
栈结点数据:第4个数据
栈结点数据:第5个数据
----------打印结束----------------------
当前栈顶数据:第5个数据
----------开始打印----------------------
栈结点数据:第1个数据
栈结点数据:第2个数据
栈结点数据:第3个数据
栈结点数据:第4个数据
----------打印结束----------------------
当前栈顶数据:第4个数据

三、案例二:单链表实现“栈” 

  1 package com.xfwl.algorithmAnalysis.stack;
  2 /**
  3  * 自定义栈结构(基于单链表的形式)
  4  * 栈的核心思想:先进后出
  5  * @function  日常学习测试
  6  * @author 小风微凉
  7  * @time  2018-5-18 下午1:49:31
  8  */
  9 public class MyStackDefin<T> {
 10     /**
 11      * 头结点
 12      */
 13     private Node<T> head;
 14     /**
 15      * 计数器
 16      */
 17     private int nodeCount=0;
 18     /**
 19      * 栈构造器
 20      */
 21     public MyStackDefin(){
 22         //重置栈结构
 23         head=new Node(null,null);
 24         nodeCount=0;
 25     }
 26     /**
 27      * 内置一个结点类
 28      */
 29     private class Node<T>{
 30         /**
 31          * 结点数据域
 32          */
 33         private T data;
 34         /**
 35          * 结点指针域
 36          */
 37         private Node<T> next;
 38         /**
 39          * 结点构造函数
 40          */
 41         public Node(T data,Node<T> node){
 42             this.data=data;
 43             this.next=node;
 44         }
 45     }
 46     /**
 47      * 数据入栈
 48      * @param data
 49      */
 50     public void push(T data){
 51         //创建一个结点
 52         Node<T> node=new Node(data,null);
 53         //入栈
 54         this.peakNode().next=node;
 55         this.nodeCount++;
 56     }
 57     /**
 58      * 数据出栈
 59      */
 60     public void pop(){
 61         //找到最后一个结点
 62         Node tmp=this.head;
 63         //判断是否只有一个头结点
 64         if(this.size()==0){
 65             System.out.println("当前栈中无数据,请先让数据入栈!");
 66             return ;
 67         }else{
 68             int count=0;
 69             while(tmp.next!=null){
 70                 if(count==(this.size()-1)){
 71                     break;
 72                 }
 73                 tmp=tmp.next;
 74                 count++;
 75             }
 76             //出栈操作
 77             tmp.next=null;
 78             this.nodeCount--;
 79         }
 80     }
 81     /**
 82      * 返回当前栈中的数据条数
 83      * @return
 84      */
 85     public int size(){
 86         return this.nodeCount;
 87     }
 88     /**
 89      * 返回栈的最顶端的元素结点
 90      * @return
 91      */
 92     public Node<T> peakNode(){
 93         Node<T> tmp=this.head;
 94         while(tmp.next!=null){
 95             tmp=tmp.next;
 96         }
 97         return tmp;
 98     }
 99     /**
100      * 返回栈的最顶端的元素
101      * @return
102      */
103     public T peak(){
104         Node<T> tmp=this.head;
105         while(tmp.next!=null){
106             tmp=tmp.next;
107         }
108         return tmp.data;
109     }
110     /**
111      * 打印当前栈信息
112      */
113     public void print(){
114         System.out.println("----------开始打印----------------------");
115         if(this.size()==0){
116             System.out.println("空栈,无检索数据!");
117         }else{
118             Node tmp=this.head.next;
119             for(int i=0;i<this.size();i++){
120                 System.out.println("栈结点数据:"+tmp.data);
121                 tmp=tmp.next;
122             }
123         }        
124         System.out.println("----------打印结束----------------------");
125     }
126 }

测试类:

package com.xfwl.algorithmAnalysis.stack;
/**
 * 测试类
 * @function  
 * @author 小风微凉
 * @time  2018-5-19 上午9:43:05
 */
public class Test {
    public static void main(String[] args) {
        //创建一个空栈
        MyStackDefin<Object> stack=new MyStackDefin<>();
        stack.print();
        System.out.println("当前栈顶数据:"+stack.peak());
        //数据入栈
        stack.push("第1个数据");
        stack.push("第2个数据");
        stack.push("第3个数据");
        stack.push("第4个数据");
        stack.push("第5个数据");
        //打印
        stack.print();
        System.out.println("当前栈顶数据:"+stack.peak());
        //数据出栈
        stack.pop();
        //打印
        stack.print();
        System.out.println("当前栈顶数据:"+stack.peak());
    }
}

运行结果:

----------开始打印----------------------
空栈,无检索数据!
----------打印结束----------------------
当前栈顶数据:null
----------开始打印----------------------
栈结点数据:第1个数据
栈结点数据:第2个数据
栈结点数据:第3个数据
栈结点数据:第4个数据
栈结点数据:第5个数据
----------打印结束----------------------
当前栈顶数据:第5个数据
----------开始打印----------------------
栈结点数据:第1个数据
栈结点数据:第2个数据
栈结点数据:第3个数据
栈结点数据:第4个数据
----------打印结束----------------------
当前栈顶数据:第4个数据

四、案例三:双链表实现“栈” 

  1 package com.xfwl.algorithmAnalysis.stack;
  2 /**
  3  * 自定义栈结构(基于双链表的形式)
  4  * 栈的核心思想:先进后出
  5  * @function  日常学习测试
  6  * @author 小风微凉
  7  * @time  2018-5-19 上午10:00:07
  8  * @param <T>
  9  */
 10 public class MyStackDefin2<T> {
 11     /**
 12      * 头结点
 13      */
 14     private Node<T> head;
 15     /**
 16      * 计数器
 17      */
 18     private int nodeCount=0;
 19     /**
 20      * 栈构造器
 21      */
 22     public MyStackDefin2(){
 23         //重置栈结构
 24         head=new Node(null,null,null);
 25         nodeCount=0;
 26     }
 27     /**
 28      * 内置一个结点类
 29      */
 30     private class Node<T>{
 31         /**
 32          * 结点数据域
 33          */
 34         private T data;
 35         /**
 36          * 结点前驱指针域
 37          */
 38         private Node<T> prev;
 39         /**
 40          * 结点后驱指针域
 41          */
 42         private Node<T> next;
 43         /**
 44          * 结点构造函数
 45          */
 46         public Node(T data,Node<T> prev,Node<T> next){
 47             this.data=data;
 48             this.prev=prev;
 49             this.next=next;
 50         }
 51     }
 52     /**
 53      * 数据入栈
 54      * @param data
 55      */
 56     public void push(T data){
 57         //创建一个结点
 58         Node<T> node=new Node(data,this.peakNode(),null);
 59         //入栈
 60         this.peakNode().next=node;
 61         this.nodeCount++;
 62     }
 63     /**
 64      * 数据出栈
 65      */
 66     public void pop(){
 67         //找到最后一个结点
 68         Node tmp=this.head;
 69         //判断是否只有一个头结点
 70         if(this.size()==0){
 71             System.out.println("当前栈中无数据,请先让数据入栈!");
 72             return ;
 73         }else{
 74             int count=0;
 75             while(tmp.next!=null){
 76                 if(count==(this.size()-1)){
 77                     break;
 78                 }
 79                 tmp=tmp.next;
 80                 count++;
 81             }
 82             //出栈操作
 83             tmp.next=null;
 84             this.nodeCount--;
 85         }
 86     }
 87     /**
 88      * 返回当前栈中的数据条数
 89      * @return
 90      */
 91     public int size(){
 92         return this.nodeCount;
 93     }
 94     /**
 95      * 返回栈的最顶端的元素结点
 96      * @return
 97      */
 98     public Node<T> peakNode(){
 99         Node<T> tmp=this.head;
100         while(tmp.next!=null){
101             tmp=tmp.next;
102         }
103         return tmp;
104     }
105     /**
106      * 返回栈的最顶端的元素
107      * @return
108      */
109     public T peak(){
110         Node<T> tmp=this.head;
111         while(tmp.next!=null){
112             tmp=tmp.next;
113         }
114         return tmp.data;
115     }
116     /**
117      * 打印当前栈信息
118      */
119     public void print(){
120         System.out.println("----------开始打印----------------------");
121         if(this.size()==0){
122             System.out.println("空栈,无检索数据!");
123         }else{
124             Node tmp=this.head.next;
125             for(int i=0;i<this.size();i++){
126                 System.out.println("栈结点数据:"+tmp.data);
127                 tmp=tmp.next;
128             }
129         }        
130         System.out.println("----------打印结束----------------------");
131     }
132 }

测试类:

package com.xfwl.algorithmAnalysis.stack;
/**
 * 测试类
 * @function  
 * @author 小风微凉
 * @time  2018-5-19 上午9:43:05
 */
public class Test2 {
    public static void main(String[] args) {
        //创建一个空栈
        MyStackDefin2<Object> stack=new MyStackDefin2<>();
        stack.print();
        System.out.println("当前栈顶数据:"+stack.peak());
        //数据入栈
        stack.push("第1个数据");
        stack.push("第2个数据");
        stack.push("第3个数据");
        stack.push("第4个数据");
        stack.push("第5个数据");
        //打印
        stack.print();
        System.out.println("当前栈顶数据:"+stack.peak());
        //数据出栈
        stack.pop();
        //打印
        stack.print();
        System.out.println("当前栈顶数据:"+stack.peak());
    }
}

运行结果:

----------开始打印----------------------
空栈,无检索数据!
----------打印结束----------------------
当前栈顶数据:null
----------开始打印----------------------
栈结点数据:第1个数据
栈结点数据:第2个数据
栈结点数据:第3个数据
栈结点数据:第4个数据
栈结点数据:第5个数据
----------打印结束----------------------
当前栈顶数据:第5个数据
----------开始打印----------------------
栈结点数据:第1个数据
栈结点数据:第2个数据
栈结点数据:第3个数据
栈结点数据:第4个数据
----------打印结束----------------------
当前栈顶数据:第4个数据

五、总结

  栈本身是一种结构思想的具现,实现的方式不固定,我们可以使用最简单的方式,或者复杂(结构层次复杂)的方式去实现,这都没问题,关键点是理解“栈”的核心思想:“先进后出”,在实际的运用场景中,我们就可以根据实际情况创造+改良来产生一套最佳的“栈”结构。

以上是关于日常学习随笔-数组单链表双链表三种形式实现栈结构的基本操作的主要内容,如果未能解决你的问题,请参考以下文章

日常学习随笔-自定义了一个双链表(注释蛮详细的)

深度解析数组单链表和双链表

数据结构单链表,双链表,数组的底层实现原理

Python数据结构与算法(2.5)——循环链表

数组模拟实现数据结构

数据结构(单链表,双链表)