数据结构中的棧在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();
}

数据结构中的棧在C#中的实现的更多相关文章

  1. 面试题:java内存中的堆区和数据结构中的堆有什么区别

    java内存中的堆是一个  链表, 数据结构中的堆:就是一个栈

  2. jvm 中内存的栈和数据结构中的栈的区别

    1.常见的数据结构:栈.队列.数组.链表和红黑树,java内存划分 2.JYM中的栈是先进先出,先入栈的先执行: 2.数据结构中的栈是先进后出,类似手枪的弹夹,先进入的子弹最后才发射: 3.数据结构中 ...

  3. [Data Structure] 数据结构中各种树

    数据结构中有很多树的结构,其中包括二叉树.二叉搜索树.2-3树.红黑树等等.本文中对数据结构中常见的几种树的概念和用途进行了汇总,不求严格精准,但求简单易懂. 1. 二叉树 二叉树是数据结构中一种重要 ...

  4. 浅析数据结构中栈与C实现

    最近在搞摄像头驱动,o()︿︶)o 唉,别提有多烦,一堆寄存器就有人受的了--特么这不是单片机的开发,这是内核驱动开发-- 今天放松一下,我们来看看数据结构中的栈,这节的知识点可以说是数据结构中最容易 ...

  5. 使用JavaScript的数组实现数据结构中的队列与堆栈

    今天在项目中要使用JavaScript实现数据结构中的队列和堆栈,这里做一下总结. 一.队列和堆栈的简单介绍 1.1.队列的基本概念 队列:是一种支持先进先出(FIFO)的集合,即先被插入的数据,先被 ...

  6. JavaScript学习总结(二十一)——使用JavaScript的数组实现数据结构中的队列与堆栈

    今天在项目中要使用JavaScript实现数据结构中的队列和堆栈,这里做一下总结. 一.队列和堆栈的简单介绍 1.1.队列的基本概念 队列:是一种支持先进先出(FIFO)的集合,即先被插入的数据,先被 ...

  7. 数据结构中常用的排序算法 && 时间复杂度 && 空间复杂度

    第一部分:数据结构中常用的排序算法 数据结构中的排序算法一般包括冒泡排序.选择排序.插入排序.归并排序和 快速排序, 当然还有很多其他的排序方式,这里主要介绍这五种排序方式. 排序是数据结构中的主要内 ...

  8. SCIP:构造数据抽象--数据结构中队列与树的解释

    现在到了数学抽象中最关键的一步:让我们忘记这些符号所表示的对象.不应该在这里停滞不前,有许多操作可以应用于这些符号,而根本不必考虑它们到底代表着什么东西. --Hermann Weyi <思维的 ...

  9. 借助 SIMD 数据布局模板和数据预处理提高 SIMD 在动画中的使用效率

    原文链接 简介 为发挥 SIMD1 的最大作用,除了对其进行矢量化处理2外,我们还需作出其他努力.可以尝试为循环添加 #pragma omp simd3,查看编译器是否成功进行矢量化,如果性能有所提升 ...

随机推荐

  1. 基础总结篇之五:BroadcastReceiver应用具体解释

    問渠那得清如許?為有源頭活水來.南宋.朱熹<觀書有感> 据说程序猿是最爱学习的群体,IT男都知道,这个行业日新月异,必须不断地学习新知识,不断地为自己注入新奇的血液,才干使自己跟上技术的步 ...

  2. Java初认识--Java中的语法结构

    Java中的语法结构(程序流程控制) Java的语法结构有四种: 1.顺序结构. 顺序结构很简单,就是按顺序执行,输出就可以了. 2.判断结构. 判断结构的一个代表性的语句是if:if语句有三种格式体 ...

  3. UVA - 11986 Save from Radiation

    Description J Save from Radiation Most of you are aware of Nuclear Power Plant Explosion at Fukushim ...

  4. Hibernate 一对多注解 mappedby 作用

    package oneToMany; import java.util.Set; import javax.persistence.*; /* 注意导入时,是导入:import javax.persi ...

  5. java设计模式之四建造者模式(Builder)

    工厂类模式提供的是创建单个类的模式,而建造者模式则是将各种产品集中起来进行管理,用来创建复合对象,所谓复合对象就是指某个类具有不同的属性,其实建造者模式就是前面抽象工厂模式和最后的Test结合起来得到 ...

  6. Python 2.7.3 Time与DateTime格式化

    import time import datetime class TimeX: '''时间工具,目前用于格式化时间''' @staticmethod def GetLocalTimeString_T ...

  7. POJ3243 EXT-BSGS算法

    需要解决问题之前,首先要做到POJ2417,我的解决问题的方法:http://blog.csdn.net/wyfcyx_forever/article/details/40538515 如今来看这个问 ...

  8. Java泛型和集合之泛型介绍

    在声明一个接口和类的时候可以使用尖括号带有一个或者多个参数但是当你在声明属于一个接口或者类的变量的时候或者你在创建一个类实例的时候需要提供他们的具体类型.我们来看下下面这个例子 List<Str ...

  9. leetcode第33题--Search for a Range

    Given a sorted array of integers, find the starting and ending position of a given target value. You ...

  10. ubuntu phone/touch的源码从哪里下载?

    这里有人在问ubuntu phone的源码从哪里下载? http://askubuntu.com/questions/237321/where-can-i-get-the-source-code-fo ...