• 栈的定义:栈是限定仅在表尾进行插入和删除的线性表。从栈的定义,我们可以知道栈是线性表的一种特殊情况,与线性表不同,栈中元素的弹出(pop)和压入(push)都只能在栈顶进行,对于我们编程来讲,我们不必考虑是否需要在某个地方插入,某个地方删除。也不必考虑在特殊节点做特别的处理。同线性表相同,栈也可以用数组或者用链表来描述。在栈中,很重要的一个东西就是栈顶,通常我们会用Top来指示栈顶所在的位置,我们可以形象地把栈必成是一叠盘子(如图1),因为盘子是一块块叠上去的,并且要拿到最后一块盘子,你必须先拿起最后一块盘子上面的盘子,这跟栈的特性先进后出一样。其中Top就是用来指向盘子顶(栈顶)的。

    image

    图1 一叠盘子

    下面我们就分别实现这数组和链表两种方式来实现栈。

    在具体地实现栈之前,我们先来实现栈的抽象接口

    interface IStack<T>

    {

        int GetLength();     //求栈的长度

        bool IsEmpty();      //判断栈是否为空

        void Clear();        //清空操作

        void Push(T item,out States mtates);   //入栈操作

        T Pop(out States mtates);              //出栈操作

        T GetTop(out States mtates);            //取栈顶元素

    }

    其中,States是一个枚举量,只有Success和Fail两种状态。

    1. 1、栈的顺序存储结构及实现

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

     

    namespace DataStructure.Stack

    {

        class SeqStack<T>: IStack<T>

        {

     

            privateconstint maxsize =100;   // 顺序栈的容量

            private T[] data =new T[maxsize];//数组,用于存储顺序栈中的数据元素

            privateint top =-1;              // 指示顺序栈的栈顶

            public SeqStack()

            {

     

            }

            public SeqStack(T[] data)

            {

                Array.Copy(data,this.data, data.Length);

                top = data.Length -1;

            }

     

     

            publicbool IsFull

            {

                get

                {

                    return top +1== maxsize ?true:false;

                }

            }

     

            publicint GetLength()

            {

                return top +1;

            }

     

            publicbool IsEmpty()

            {

                return top ==-1?true:false;

            }

     

            publicvoid Clear()

            {

                top =-1;

            }

     

            publicvoid Push(T item,out States states)

            {

                if(IsFull ==true)

                {

                    states = States.Fail;

     

                }

                else

                {

                    states = States.Success;

                    data[++top]= item;

                }

            }

     

            public T Pop(out States states)

            {

                if(IsEmpty()==true)

                {

                    states = States.Fail;

                    returndefault(T);

                }

                else

                {

                    states = States.Success;

                    return data[top--];

                }

            }

     

            public T GetTop(out States states)

            {

                if(IsEmpty()==true)

                {

                    states = States.Fail;

                    returndefault(T);

                }

                else

                {

                    states = States.Success;

                    return data[top];

                }

            }

        }

    }

     

     

    1. 2、两栈共享空间

    2. 对于两栈共享空间,我们的构想是当Stack1空间不够的时候,就挪用Stack2的空间。为了不影响Stack2的正常使用,当Stack1空间不够时,我们将从Stack2的尾部开始挪用他的空间。两栈共享空间将大大提高空间的利用率。(两栈共享空间的示意图如下)

    3. image

    1. 在这里,我们需要对原先的栈的顺序存储结构进行一些改造,主要的改造是:

    2. 1、将栈的存储容量由原来的在代码中直接指定,改成由构造函数指定;

    3. 2、创建一个新的方法 public void UseExtraSpace(SeqStack<T> Stack2),用来注入另一个栈的引用。注意,这里两个栈的类型必须是相同的;

    4. 3、增加一个用来保存另一个栈引用的字段otherStack;

    5. 4、增加一个字段来保存第二个栈的Top。

    6. 5、为了方便对Stack2中的数据域进行操作,我们将Stack中的数据域的可访问性变成Public。

    在以下的代码中,我们认为Stack1和Stack2要么数据域没有值,要么至少有一个值。

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

     

    namespace DataStructure.Stack

    {

        class SeqStack<T>: IStack<T>

        {

     

            privateint top1 =-1;              // 指示顺序栈的栈顶

            privateint top2 =-1;

            privateint maxsize;

     

            publicint MaxSize

            {

                get {return maxsize;}

                private set { maxsize = value;}

            }

            public T[] data;                  //数组,用于存储顺序栈中的数据元素

            SeqStack<T> otherStack;

            public SeqStack()

            {

     

            }

            /// <summary>

            /// SeqStack构造函数

            /// </summary>

            /// <param name="MaxSize"> 顺序栈的容量 </param>

            public SeqStack(int MaxSize)

            {

                data =new T[MaxSize];

                this.maxsize = MaxSize;

     

            }

            public SeqStack(T[] data)

            {

                data =new T[4];//数组,用于存储顺序栈中的数据元素

                Array.Copy(data,this.data, data.Length);

                top1 = data.Length -1;

                this.maxsize =4;

     

            }

     

            privatevoid IsUseExtraSpace(){

              

                if(otherStack!=null)

                {

                    bool isUseTop2 = top2 ==(otherStack.MaxSize -1)?false:true;

                }

                else

                {

     

                }

            }

            /// <summary>

            /// 使用两栈共享空间

            /// </summary>

            /// <param name="Stack2">2</param>

            /// <returns>操作是否成功</returns>

            publicbool UseExtraSpace(SeqStack<T> Stack2)

            {

                if(this.GetType()==Stack2.GetType())

                {

                      this.otherStack = Stack2;

                      top2 = Stack2.MaxSize -1;

                      returntrue;

                }

                else

                {

                    returnfalse;

                }

             

            }

     

            publicbool IsThisStackFull

            {

                get

                {

                    return lenth >= maxsize ?true:false;

                }

            }

            privateint lenth=0;

     

            publicint Lenth

            {

                get {return lenth;}

                private set { lenth = value;}

            }

           

            publicint GetLength()

            {

                return Lenth;

            }

     

            publicbool IsEmpty()

            {

                return top1 ==-1?true:false;

            }

     

            publicvoid Clear()

            {

                top1 =-1;

            }

     

            publicvoid Push(T item,out States states)

            {

                if(IsThisStackFull ==true)

                {

                  bool  IsStack2Full =(top2-(otherStack.GetLength()-1))  ==1;//如果top2Stack2top相邻,就说明Stack2满了

                  if(otherStack !=null&&!IsStack2Full)

                    {

                       states=  otherStack.InsertFromButtom(top2--, item);

                       this.lenth++;

                    }

                    else

                    {

                        states =  States.Fail;

                    }

                  

                }

                else

                {

                    states = States.Success;

                    this.lenth++;

                    data[++top1]= item;

                }

            }

            public States InsertFromButtom(int index,T item){

                //判断栈2是否已经满了

                if((index -(this.GetLength()-1))==0)//满了

                {

                    return States.Fail;

                }

                else//未满

                {

                    this.data[index]= item;

                    return States.Success;

                }

            }

            public T Pop(out States states)

            {

                if(IsEmpty()==true)

                {

                    states = States.Fail;

                    returndefault(T);

                }

                else

                {

                    states = States.Success;

                    T dataToReturn =this.GetLength()<=this.MaxSize ?this.data[top1--]:this.otherStack.data[++top2];

                    this.lenth--;;//top-1+1=top

                    return dataToReturn;

                }

            }

     

            public T GetTop(out States states)

            {

                if(IsEmpty()==true)

                {

                    states = States.Fail;

                    returndefault(T);

                }

                else

                {

                    states = States.Success;

                    T dataToReturn =this.GetLength()<=this.MaxSize ?this.data[top1]:this.otherStack.data[top2];

                    return dataToReturn;

                }

            }

        }

    }

     

    总结:两栈共享空间的难度主要在于出栈和入栈时对Stack1或者Stack2的选择上,其中我们可以利用Stack1.getLenth来判断,当Stack1.getLenth大于Stack1.MaxSize时,选择用Stack2;反之,选择Stack1.

    1. 3、栈的链式存储结构及实现

    2. 栈的链式存储结构简称链栈。链栈和普通的单链表比较,他们的不同之处基本上也就是插入和删除都在栈定进行这点不同。在栈的顺序存储结构中,我们需要考虑在数组的开头或结尾作为栈顶,最后我们选择了在数组的结尾作为栈顶。在单链表中,我们是不是也使用链表的尾巴来作为栈顶呢?如果我们使用链表尾作为栈顶,那么我们需要保存一个头节点和一个尾节点。或者保存一个头节点,然后每次都遍历到链表尾(时间复杂度为O(n))。其实在单链表中,我们已经引入了头节点,当我们从头节点处开始弹出(Pop)或压入(Push)元素的时候,我们就可以重复利用头节点,将头节点作为栈顶(Top)。

    3. 链栈实现的代码

    4. using System;

      using System.Collections.Generic;

      using System.Linq;

      using System.Text;

       

      namespace DataStructure.Stack

      {

          class LinkStack<T>: IStack<T>

          {

       

              class Node<T>

              {

       

                  private T data;

                  /// <summary>

                  /// 数据域

                  /// </summary>

                  public T Data

                  {

                      get {return data;}

                      set { data = value;}

                  }

       

       

                  private Node<T> next;

                  /// <summary>

                  /// 引用域

                  /// </summary>

                  public Node<T> Next

                  {

                      get {return next;}

                      set { next = value;}

                  }

       

                  //头结点构造函数

                  public Node(Node<T> node)

                      :this(default(T), node)

                  {

                  }

                  //普通结点构造函数

                  public Node(T data, Node<T> node)

                  {

                      this.Data = data;

                      this.Next = node;

                  }

                  /// <summary>

                  /// 空构造函数

                  /// </summary>

                  public Node()

                      :this(default(T),null)

                  {

                  }

                  //尾结点构造函数

                  public Node(T data)

                      :this(data,null)

                  {

       

                  }

              }

       

              privateint lenth=0;

       

              publicint Lenth

              {

                  get {return lenth;}

                  set { lenth = value;}

              }

       

              private Node<T> top;

              public LinkStack()

              {

       

              }

              public LinkStack(T[] t)

              {

                  States mStates;

                  for(int i =0; i < t.Length; i++)

                  {

                      this.Push(t[i],out mStates);

                  }

              }

       

       

             

              publicint GetLength()

              {

                  returnthis.Lenth;

              }

       

              publicbool IsEmpty()

              {

                  return top ==null?true:false;

              }

       

              publicvoid Clear()

              {

                  this.top =null;

              }

       

              publicvoid Push(T item,out States states)

              {

                

                  if(this.top==null)//头节点

                  {

                      this.top =new Node<T>(item);

                  }else              //普通节点

                  {

                      Node<T> NodeToPush =new Node<T>(item,this.top);

                      this.top = NodeToPush;

                  }

                  states = States.Success;

                  this.lenth++;

       

              }

       

              public T Pop(out States states)

              {

                  if(this.IsEmpty()==true)

                  {

                      states = States.Fail;

                      returndefault(T);

                  }

                  Node<T> NodeToPop=this.top;

                  this.top = NodeToPop.Next;

                  this.Lenth--;

                  states = States.Success;

                  return NodeToPop.Data;

              }

       

              public T GetTop(out States states)

              {

                  if(IsEmpty()==true)

                  {

                      states = States.Fail;

                      returndefault(T);

                  }

                  else

                  {

                      states = States.Success;

                      returnthis.top.Data;

                  }

       

              }

          }

      }

       

  • 相关阅读:
    字典
    字符串常用的方法
    切片,集合、文件处理
    蓝桥杯练习 Day6 题解
    spoj-ORDERS
    spoj-SUBSUMS
    spoj
    spoj --- ABCDEF
    C. Andryusha and Colored Balloons
    B. The Meeting Place Cannot Be Changed
  • 原文地址:https://www.cnblogs.com/kissazi2/p/3200856.html
Copyright © 2020-2023  润新知