栈的定义:栈是限定仅在表尾进行插入和删除的线性表。从栈的定义,我们可以知道栈是线性表的一种特殊情况,与线性表不同,栈中元素的弹出(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;

                }

     

            }

        }

    }

     

posted @ 2013-07-19 16:39  陈哈哈  阅读(433)  评论(0编辑  收藏  举报