Fork me on GitHub
数据结构中的棧在C#中的实现

数据结构中的棧在C#中的实现

一、大致学习

棧是一种面向表的数据结构,棧中的数据只能在标的某一短进行添加和删除操作,是一种典型的(LIFO)数据结构。

现实生活中的理解:自助餐厅的盘子堆,人们总是从顶部取走盘子,当洗碗工把洗好的盘子放回盘子堆的时候也是放在盘子堆的顶部。

Stack类实现棧:Stack<T> number=new Stack<T>();

Stack类是ICollection接口的一个实现(foreach),它代表了一个LIFO群集或一个棧,在.NET中作为循环缓冲来实现的,这使得能动态地分配进栈数据项的空间;

Stack构造器方法,默认的构造器实例化的是一个具有10个数值初始容量的空栈,每当棧达到满容量时就会把容量值翻倍;另一种构造器允许创建一个来自另一个群集对象的棧对象

如:

string [] names= new string[]{"jack","rose","jeff"};

Stack nameStack=new Stack(names);

二、具体分析

C#Stack泛型类的常用方法介绍:

1、Push(object item)方法:将对象插入栈顶,同时将棧的初始变量+1

 public void Push(object item)
 {
       list.Add(item);
        p_index++;
  }

2、Pop()方法:将对象移除栈顶,同时将棧的初始变量-1,返回出棧的对象

复制代码
 public object Pop()
 {
       object obj=list[p_index];
       list.RemoveAt(p_index);
       p_index--;
       return obj;
}
复制代码

3、Peek()方法:取数,只是查看栈顶元素的”值“

       public object Peek()
        { 
            return list[p_index];
        }

4、Clear()方法:清空棧内数据,将数据项计数器设置为0

        public void Clear()
        {
            list.Clear();
            p_index = -1;
        }

5、Contains()方法:用来确定指定的元素是否在棧内 bool

        public bool Contains(object item)
        {
            return list.Contains(item);
        }

6、CopyTo()方法:将棧内的内容复制到一个数组中,要求数组必须是object类型的,因为这是所有棧对象的数据类型。包含两个参数:一个数组和起始索引值

复制代码
Stack myStack=new Stack();
for(int i=20;i>0;i--)
{
    myStack.Push(i);
}
object [] myArray=new object[myStack.Count];
myStack.CopyTo(myArray,0);
复制代码

7、ToArray()方法:复制到一个新的数组中,不含索引值,故需创建新的数组

复制代码
Stack myStack=new Stack();
for(int i=0;i>0;i++)
{
    myStack.Push(i);
}
object [] myArray=new object[myStack.Count];
myArray=myStack.ToArray();
复制代码

8、Count属性:获取棧中的元素个数

复制代码
public int Count
{
     get 
     {
           return list.Count; 
      }
}
复制代码

三、案例分析

1、使用棧来判断回文

把相同的词汇或句子,在下文中调换位置或颠倒过来,产生首尾回环的情趣,叫做回文,也叫回环。

复制代码
class CStack
    {
        private int p_index;
        private ArrayList list;
        public CStack()
        {
            list = new ArrayList();
            p_index = -1;
        }
        //获取棧的空间
        public int Count
        {
            get 
            {
                return list.Count; 
            }
        }
        //进栈
        public void Push(object item)
        {
            list.Add(item);
            p_index++;
        }
        //出棧
        public object Pop()
        {
            object obj=list[p_index];
            list.RemoveAt(p_index);
            p_index--;
            return obj;
        }
        //清空棧内元素
        public void Clear()
        {
            list.Clear();
            p_index = -1;
        }
        //取数
        public object Peek()
        { 
            return list[p_index];
        }
        public bool Contains(object item)
        {
            return list.Contains(item);
        }
    }
复制代码
复制代码
static void Main(string[] args)
        {
            CStack alist = new CStack();
            string ch;
            string word = "woainiiniaow";
            bool isPalindrome = true;
            //将word反转存入棧中
            for (int i = 0; i < word.Length;i++ )
            {
                alist.Push(word.Substring(i,1));
            }
            //进行判断
            int pos = 0;
            while(alist.Count>0)
            {
                ch = alist.Pop().ToString();
                if (ch != word.Substring(pos, 1))
                {
                    isPalindrome = false;
                    break;
                }
                else 
                {
                    pos++;
                }
            }
            if (isPalindrome)
            {
                Console.WriteLine("{0}是回文", word);
            }
            else
            {
                Console.WriteLine("{0}不是回文", word); 
            }
            Console.ReadKey();
        } //另外我觉得可采用另一种常规方法就是复制一个“数组”,原“数组”从0->Length遍历,新“数组”从Length->0遍历,进行比对。
复制代码

2、使用棧来实现四则运算

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Collections;

namespace _09使用棧来实现四则运算
{
    class Program
    {
        static void Main(string[] args)
        {
            Stack nums = new Stack();
            Stack ops = new Stack();
            string expression = "5*2";
            Calculate(nums,ops,expression);
            Console.WriteLine(nums.Pop());
            Console.ReadKey();
        }
        /// <summary>
        /// 判断是否是数字
        /// </summary>
        /// <param name="input">要判断参数</param>
        /// <returns></returns>
        static bool IsNumeric(string input)
        {
            bool flag = true;
            string pattern=(@"^\d+$");
            Regex validate = new Regex(pattern);
            if(!validate.IsMatch(input))
            {
                flag = false;
            }
            return flag;
        }
        /// <summary>
        /// 进栈操作
        /// </summary>
        /// <param name="N">保存数字的棧</param>
        /// <param name="O">保存运算符的棧</param>
        /// <param name="exp">运算表达式</param>
        static void Calculate(Stack N,Stack O,string exp)
        {
            string ch, token = "";
            for (int i = 0; i < exp.Length;i++ )
            {
                ch = exp.Substring(i,1);
                if (IsNumeric(ch)) 
                {
                    token = ch;
                    N.Push(token);
                    token = "";
                }
                //if(ch==""||i==(exp.Length-1))
                //{
                //    N.Push(token);
                //    token = "";
                //}
                else if(ch=="+"||ch=="-"||ch=="*"||ch=="/")
                {
                    O.Push(ch);
                }
                if(N.Count==2)
                {
                    Compute(N,O);
                }
            }
            
        }
        /// <summary>
        /// 进行运算
        /// </summary>
        /// <param name="N">参与运算的数字的棧</param>
        /// <param name="O">参与运算的运算符的棧</param>
        static void Compute(Stack N,Stack O)
        {
            int oper1;
            int oper2;
            string oper;
            oper1 = Convert.ToInt32(N.Pop());
            oper2 = Convert.ToInt32(N.Pop());
            oper = Convert.ToString(O.Pop());
            switch(oper)
            {
                case"+":
                    N.Push(oper1+oper2);
                    break;
                case "-":
                    N.Push(oper1-oper2);
                    break;
                case "*":
                    N.Push(oper1*oper2);
                    break;
                case "/":
                    if (oper2 == 0)
                    {
                        throw new Exception("除数不能为0");
                    }
                    N.Push(oper1/oper2);
                    break;
            }
        }
    }
}
复制代码

3、十进制向多种进制进行转换

复制代码
static void Main(string[] args)
        {
            int num, baseNum;
            Console.Write("Enter a decimal number");
            num = Convert.ToInt32(Console.ReadLine());
            Console.Write("Enter a base");
            baseNum = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine(num+"converts to");
            MulBase(num,baseNum);
            Console.WriteLine("Base"+baseNum);
            Console.ReadKey();
        }
        static void MulBase(int n,int b)
        {
            Stack digits = new Stack();
            do
            {
                digits.Push(n%b);
                n /= b;
            }while(n!=0);
            while(digits.Count>0)
            {
                Console.Write(digits.Pop());
            }
        }
复制代码

4、火车进站调度重组问题在C#中的实现

问题描述:假设一列货运列车共有n节编号分别为1~n的车厢,在进站前这n节车厢并不是按其编号有序排列;现要求重新排列各车厢,使该列车在

进入车站时,所有的车厢从前到后按编号1~n的次序排列。

复制代码
interface IStack<T>
    {
        void Push(T item);//进栈操作
        T Pop();//出棧操作
        T Peek();//取数操作
        int GetLength();//求棧的长度
        bool IsEmpty();//判断棧是否为空
        void Clear();//清空棧操作
    }
复制代码
复制代码
 class SeqStack<T>:IStack<T>
    {
        //顺序栈的容量
        private int maxsize;
        //用于存储数序中的数据元素
        private T[] data;
        //指示顺序栈的栈顶
        private int top;
        //构建索引器
        public T this[int index]
        {
            get
            { 
                return data[index];
            }
            set
            {
                data[index] = value;
            }
        }
        //棧容量属性
        public int Maxsize
        {
            get
            {
                return maxsize;
            }
            set
            {
                maxsize = value;
            }
        }
        //栈顶属性
        public int Top
        {
            get
            {
                return top;
            }
        }
        //初始化棧
        public SeqStack(int size)
        {
            data=new T[size];
            maxsize = size;
            top = -1;
        }
        //判断棧是否满
        public bool IsFull()
        {
            if (top == maxsize - 1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        //判断棧是否为空
        public bool IsEmpty()
        {
            if (top == -1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        //进栈操作
        public void Push(T item)
        {
            if (IsFull())
            {
                Console.WriteLine("Stack is full");
                return;
            }
            else
            { 
                data[++top]=item;
            }
        }
        //出棧操作
        public T Pop()
        {
            T temp=default(T);
            if (IsEmpty())
            {
                Console.WriteLine("Stack is empty");
                return temp;
            }
            else
            {
                temp = data[top];
                --top;
                return temp;
            }
        }
        //获取栈顶元素
        public T Peek()
        { 
            if(IsEmpty())
            {
                Console.WriteLine("Stack is empty");
                return default(T);
            }
            else
            {
                return data[top];
            }
        }
        //获取棧的长度
        public int GetLength()
        {
            return top + 1;
        }
        //清空棧
        public void Clear()
        {
            top = -1;
        }
    }
复制代码
复制代码
class TrainAyyayrangeByStack
    {
        //车厢重排算法,K个缓冲铁轨,车厢初始排序存放在p中
        public bool Railroad(int[] p, int n, int k)
        {
            //重排成功返回true,否则返回false
            //创建与缓冲铁轨对应的堆栈
            SeqStack<int>[] H = new SeqStack<int>[k+1];
            for (int i = 1; i <= k;i++ )
            {
                H[i] = new SeqStack<int>(p.Length);
            }
            //初始化第一个出棧车厢号1
            int NowOut = 1;
            //初始设置缓冲铁轨中编号最小的车厢
            int minH = n+1;
            //初始minH号车厢对应的缓冲铁轨号
            int minS = 0;
            //车厢重排
            for (int i = 0; i < n;i++ )
            {
                //如果即将入站的车厢号和下一个即将出站的车厢号一致,就直接输出
                if (p[i] == NowOut)
                {
                    Console.WriteLine("Move Car {0} from input to output", p[i]);
                    //输出后将下一个即将出站的车厢号重置
                    NowOut++;
                    //从缓冲铁轨中输出
                    while (minH == NowOut)
                    {
                        Output(ref minH, ref minS, ref H, k, n);
                        NowOut++;
                    }
                }
                //如果即将入站的车厢号和下一个即将出战的车厢号不一致,就将其保存在缓冲铁轨中
                else
                { 
                    //将p[i]送入某个缓冲铁轨
                    if(!Hold(p[i],ref minH,ref minS,ref H,k,n))
                    {
                        return false;
                    }
                }              
            } return true;
        }
        //把车厢从缓冲铁轨送至出轨处,同时修改minS和minH
        void Output(ref int minH,ref int minS,ref SeqStack<int>[]H,int k,int n)
        {
            //车厢索引
            int c;
            //从堆栈minS中删除编号最小的车厢minH
            c = H[minS].Pop();
            Console.WriteLine("Move car {0} from holding track {1} to output",c,minS);
            //通过检查所有的栈顶,搜索新的minH和minS
            minH = n + 2;
            for (int i = 1; i <= k;i++ )
            {
                if(!H[i].IsEmpty()&&(H[i].Peek())<minH)
                {
                    minH = H[i].Peek();
                    minS = i;
                }
            }
        }
        //在一个缓冲铁轨中放入车厢c
        bool Hold(int c,ref int minH,ref int minS,ref SeqStack<int>[]H,int k,int n)
        {
            //如果没有可用的缓冲铁轨,则返回false
            //否则返回true
            //为车厢c寻找最优的缓冲铁轨
            //初始化最优铁轨和最优栈顶车厢号
            int BestTrack = 0;
            int BestTop = n + 1;
            //车厢索引
            int x;
            //扫描缓冲铁轨,寻找最优的缓冲铁轨棧,即栈顶元素相对最小
            for (int i = 1; i <= k;i++ )
            {
                //如果缓冲铁轨不为空
                if (!H[i].IsEmpty())
                {
                    x = H[i].Peek();
                    if (c < x && x < BestTop)
                    {
                        //铁轨i顶部的车厢编号最小
                        BestTop = x;
                        BestTrack = i;
                    }
                }
                //铁轨i为空
                else
                { 
                    if(BestTrack==0)
                    {
                        BestTrack = i;
                    }
                    break;
                }
            }
            //没有可用铁轨
            if(BestTrack==0)
            {
                return false;
            }
            //把车厢c送入缓冲铁轨
            H[BestTrack].Push(c);
            Console.WriteLine("Move car {0} from input to holding track {1}",c,BestTrack);
            //如果条件成立就修改缓冲铁轨中下一个将要出站的车厢号
            if (c < minH)
            {
                minH = c;
                minS = BestTrack;
            }
            return true;
        }
复制代码
复制代码
static void Main(string[] args)
        {
            int[] p = new int[] { 3,6,9,2,4,7,1,8,5};
            int k = 3;
            TrainAyyayrangeByStack ta = new TrainAyyayrangeByStack();
            bool result;
            result = ta.Railroad(p,p.Length,k);

            do
            {
                if(result==false)
                {
                    Console.WriteLine("need more holding track,please enter additional");
                    k = k + Convert.ToInt32(Console.ReadLine());
                    result = ta.Railroad(p,p.Length,k);
                }
            }while(result==false);
            Console.ReadKey();
        }
复制代码

 

 

posted on 2013-07-16 13:53  HackerVirus  阅读(258)  评论(0编辑  收藏  举报