堆栈推送和流行

时间:2013-12-17 20:01:09

标签: c# stack

我正在努力让我的推送和流行方法正常工作,但似乎无法做到。使用Push方法,我认为这与nextfree有关,但我不确定。另外,使用Pop方法,我不确定如何做,我将把我的伪代码放在我的实际代码下面。 这是我的代码:

class Program
{

   private string[] Stack = new string[5];
   int nextFree = 3;

    public Program() 
    {

        Stack = new string[5];

        Stack[0] = "Greg";
        Stack[1] = "Matt";
        Stack[2] = "Jack";
        Stack[3] = "Fred";


    }

    static void Main(string[] args)
    {
        Program prog = new Program();
        do
        {
            prog.DisplayMenu();
        }
        while (true);
    }




    public void DisplayMenu()
    {
        Int32 userInput = 0;

        Console.WriteLine("Linear Stack");
        Console.WriteLine("1: Add to stack");
        Console.WriteLine("2: Delete from stack");
        userInput = Int32.Parse(Console.ReadLine());


        switch (userInput)
        {
            case 1:
                this.Push();
                break;

            case 2:
                this.Pop();
                break;
        }

    }


    public void Push()
    {


        if (nextFree == Stack.Length)
        {
            Console.WriteLine("Stackoverflow, to many elements for the stack");
            Console.ReadLine();
        }
        else
        {
            Console.WriteLine("Please enter a name to be added");
            string userInput = Console.ReadLine();

            nextFree++;
            Stack[nextFree] = userInput;

        }
        this.list();
    }


        public void Pop()
        {
            if (nextFree == -1)
            {
                Console.WriteLine("Stack is empty");
                Console.ReadLine();
            }
            else
            {

                nextFree--;
            }

            this.list();
        }

        public void list()
        {
            foreach (string s in Stack)
            {
                Console.Write(s + " ");
            }

            Console.WriteLine();
        }



  }
}

Pop伪代码:

If Stack is empty
Then error
Else
Return Stack[TopOfStackPointer]
Decrement TopOfStackPointer
EndIF

更新: Push方法现在可以使用值3启动nextFree。

6 个答案:

答案 0 :(得分:4)

首次启动时,您需要将nextFree的值实例化为4(因为您的堆栈中已有4个项目)。

当检查nextFree的值是否超出not的范围时,您需要记住数组索引是基于零的(即它们从0开始)。所以你的情况应该是:

if(nextFree >= Stack.Length - 1)

答案 1 :(得分:2)

试试这段代码。还要确保与您的版本进行比较,以了解您的问题所在。

        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;

        namespace ConsoleApplication12
        {
            class Program
            {

                private string[] Stack = new string[5];
                private int nextFree;

                public Program()
                {
                    Stack = new string[10];
                    Stack[0] = "Greg";
                    Stack[1] = "Matt";
                    Stack[2] = "Jack";
                    Stack[3] = "Fred";
                    nextFree = 4;
                }

                static void Main(string[] args)
                {
                    Program prog = new Program();
                    do
                    {
                        prog.DisplayMenu();
                    }
                    while (true);
                }




                public void DisplayMenu()
                {
                    Int32 userInput = 0;

                    Console.WriteLine("Linear Stack");
                    Console.WriteLine("1: Add to stack");
                    Console.WriteLine("2: Delete from stack");
                    String s = Console.ReadLine().Trim();
                    try
                    {
                        userInput = Int32.Parse(s);
                    }
                    catch (Exception)
                    {
                        userInput = 1;
                    }

                    switch (userInput)
                    {
                        case 1:
                            this.Push();
                            break;

                        case 2:
                            this.Pop();
                            break;
                    }

                }


                public void Push()
                {
                    if (nextFree == Stack.Length)
                    {
                        Console.WriteLine("Stackoverflow, to many elements for the stack");
                        Console.ReadLine();
                    }
                    else
                    {
                        Console.WriteLine("Please enter a name to be added");
                        string userInput = Console.ReadLine();
                        Stack[nextFree] = userInput;
                        nextFree++;
                    }
                    this.List();
                }


                public String Pop()
                {
                    if (nextFree == 0)
                    {
                        Console.WriteLine("Stack is empty");
                        return null;
                    }
                    else
                    {
                        String res = Stack[nextFree - 1];
                        nextFree--;
                        this.List();
                        return res;
                    }
                }

                public void List()
                {
                    for (int k = 0; k < nextFree; k++)
                    {
                        Console.Write(this.Stack[k] + " ");
                    }
                    Console.WriteLine();
                }
            }

        }

答案 2 :(得分:2)

您的Pop方法已基本完成,您需要的最后一步是在递减索引之前实际从数组中删除值,以“弹出”它。您可以将之前的值设置为null

    public void Pop()
    {
        if (nextFree == -1)
        {
            Console.WriteLine("Stack is empty");
            Console.ReadLine();
        }
        else
        {
            Stack[nextFree] = null;
            nextFree--;
        }

        this.list();
    }

您也可以通过添加

来获取之前显示的内容
string value = Stack[nextFree];
Console.WriteLine("Just popped value: " + value);

将其设置为null

这里没有必要像你的伪代码那样实际返回它,因为你没有使用外面的值。如果需要,请考虑将代码更改为

    public string Pop()
    {
        string value = string.Empty;

        if (nextFree == -1)
        {
            Console.WriteLine("Stack is empty");
            Console.ReadLine();
        }
        else
        {
            value = Stack[nextFree];
            Stack[nextFree] = null;
            nextFree--;
        }

        this.list();
        return value;
    }

请注意,返回类型也从void更改为string

答案 3 :(得分:1)

这是我的堆栈实现。

public class MStack<T> : IEnumerable<T>
{
    private readonly List<T> stack = new List<T>();

    public void Push(T item)
    {
        stack.Add(item);
    }

    public T Pop()
    {
        var item = Peek();
        stack.Remove(Peek());
        return item;
    }

    public T Peek()
    {
        return stack[stack.Count - 1];
    }

    public int Count { get { return stack.Count; } }

    public IEnumerator<T> GetEnumerator()
    {
        for (int i = 0; i < stack.Count; i++)
            yield return Peek();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

答案 4 :(得分:0)

我喜欢MStack课程的想法(参见Raz Megrelidze的回答)。但是,实现堆栈的一维列表的问题在于它无法处理重复值。因此,在许多情况下,它是一个失败的堆栈。

所以这是我的词典变体,它可以处理重复。

public class MStack<T> : IEnumerable<T>
{
    private readonly Dictionary<int, T> stack = new Dictionary<int, T>();

    public void Push(T item)
    {
        stack.Add(stack.Count, item);
    }

    public T Pop()
    {
        var item = Peek();
        stack.Remove(stack.Count - 1);
        return item;
    }

    public T Peek()
    {
        return stack[stack.Count - 1];
    }

    public int Count { get { return stack.Count; } }

    public IEnumerator<T> GetEnumerator()
    {
        for (int i = 0; i < stack.Count; i++)
            yield return Peek();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

答案 5 :(得分:0)

最新答案-您可以像在Javascript / TypeScript中一样使用 Push and Pop for C#来轻松实现它们:数组正在使用它们。优点是您不必关心重复的值-新元素仅附加到数组中。

C#中,您可以这样操作(请注意,JavaScript与Push语言有一个区别-我返回的是数组,而不仅仅是新的长度,因为我认为这样做更有意义):

void Main()
{
    T[] Push<T>(ref T[] ar, params T[] items)
    {
        var arLength=ar.Length;
        Array.Resize(ref ar, arLength + items.Length);
        for (int i = arLength, j=0; i < arLength + items.Length; i++, j++)
        {
            ar[i] = items[j];
        }
        return ar;
    }
    T Pop<T>(ref T[] ar) 
    { 
        T item = default(T); 
        if (ar.Length > 0) 
        { 
            var tmp = ar.ToList(); item = tmp.LastOrDefault();              
            Array.Resize(ref ar, ar.Length - 1);
        }; 
        return item; 
    }   

   // Example 1: Create a numeric array
   var arr = new[] { 1, 2, 3, 4 };

   // Push 5, 6, 7 to the end
   Push(ref arr, 5, 6, 7).Dump();

   // Pop the last element (7)
   Pop(ref arr).Dump(); arr.Dump();

   // Example 2: "Stack" array 
   var Stack=new[] {"Greg", "Matt"};
   Push(ref Stack, "Jack", "Fred"); Stack.Dump();
   var elem=Pop(ref Stack); elem.Dump(); Stack.Dump();
}

DotNetFiddle

这些函数是通用的,您可以将其用于每种类型的数组。
用法示例:

var emptyIntArray = new int[0]; // empty array: specify type + length=0
var emptyStrArray = new string[0]; // empty array: specify type + length=0
var arr = new[] { 1, 2, 3, 4 }; // example array. can be strings as well!

流行:

Pop(ref arr); // removes the item with highest index
var item = Pop(ref arr); // removes the item with highest index, returns it
Pop(ref emptyIntArray); // returns 0 (default for int)
Pop(ref emptyStrArray); // returns null (default for string)

推送:

Push(ref arr, 5); // adds element 5 (increases array size by 1)
Push(ref arr, 6, 7, 8); // adds elements 6, 7, 8 (increases array size by 3)
var newLen = Push(ref arr, 9).Length; // adds element 9, returns new length

注意,我正在使用 ref 参数,因为我不想通过创建整个阵列的副本来浪费内存。这可以通过调整数组大小来实现。由于存在ref参数,因此PushPop不能作为扩展方法。


程序示例的输出:

  

转储对象(Int32 [])   
[1,2,3,4,5,6,7]   
转储对象(Int32)   
7   
转储对象(Int32 [])   
[1,2,3,4,5,6]   
转储对象(字符串[])   
[格雷格,马特,杰克,弗雷德]   
转储对象(字符串)   
弗雷德   
转储对象(字符串[])   
[格雷格,马特,杰克]