Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C#

Tạo Stack từ collection trong C#

Stack<T> cung cấp constructor nhận IEnumerable<T> cho phép tạo Stack mới từ một collection đã có. Lưu ý: Stack tuân theo nguyên tắc LIFO (Last In, First Out), nên thứ tự phần tử trong Stack mới sẽ **ngược lại** thứ tự trong collection nguồn khi duyệt bằng foreach.

Ví dụ 1: Tạo Stack<int> từ Stack khác qua ToArray()

using System;
using System.Collections.Generic;

public class Demo
{
    public static void Main()
    {
        Stack<int> stack = new Stack<int>();
        stack.Push(100);
        stack.Push(200);
        stack.Push(300);
        stack.Push(400);
        stack.Push(500);
        stack.Push(600);
        stack.Push(700);
        stack.Push(800);
        stack.Push(900);
        stack.Push(1000);

        Console.WriteLine("Các phần tử Stack gốc (LIFO - top đầu tiên)...");
        foreach (int val in stack)
        {
            Console.WriteLine(val);
        }

        // Tạo Stack mới từ mảng của stack gốc
        Stack<int> arr = new Stack<int>(stack.ToArray());

        Console.WriteLine("\nCác phần tử Stack mới (từ ToArray)...");
        foreach (int val in arr)
        {
            Console.WriteLine(val);
        }
    }
}

Kết quả

Các phần tử Stack gốc (LIFO - top đầu tiên)...
1000
900
800
700
600
500
400
300
200
100

Các phần tử Stack mới (từ ToArray)...
100
200
300
400
500
600
700
800
900
1000

Ví dụ 2: Stack<string>

using System;
using System.Collections.Generic;

public class Demo
{
    public static void Main()
    {
        Stack<string> stack = new Stack<string>();
        stack.Push("Katie");
        stack.Push("Andy");
        stack.Push("Ariane");
        stack.Push("Justin");

        Console.WriteLine("Các phần tử Stack gốc...");
        foreach (string val in stack)
        {
            Console.WriteLine(val);
        }

        Stack<string> arr = new Stack<string>(stack.ToArray());

        Console.WriteLine("\nCác phần tử Stack mới (từ ToArray)...");
        foreach (string val in arr)
        {
            Console.WriteLine(val);
        }
    }
}

Kết quả

Các phần tử Stack gốc...
Justin
Ariane
Andy
Katie

Các phần tử Stack mới (từ ToArray)...
Katie
Andy
Ariane
Justin

Giải thích thứ tự phần tử

📌 Quan trọng: Constructor Stack<T>(IEnumerable<T>) thêm các phần tử theo thứ tự duyệt của IEnumerable. Vì stack.ToArray() trả về mảng theo thứ tự **top-to-bottom** (phần tử top ở index 0), Stack mới sẽ có thứ tự **ngược lại** stack gốc.
Stack gốc (Push: 1, 2, 3):
Top -> 3, 2, 1 <- Bottom

stack.ToArray() -> [3, 2, 1] (index 0 = top)

Stack mới từ constructor IEnumerable:
Push 3 -> Push 2 -> Push 1
Top -> 1, 2, 3 <- Bottom (NGƯỢC LẠI!)

Cách tạo Stack giữ nguyên thứ tự LIFO

// Cách 1: Reverse trước khi tạo
Stack<int> newStack = new Stack<int>(stack.Reverse());
// Hoặc
Stack<int> newStack = new Stack<int>(stack.ToArray().Reverse());

// Cách 2: Dùng constructor rồi Push lại (nếu cần logic phức tạp)
Stack<int> newStack = new Stack<int>();
foreach (var item in stack)
{
    newStack.Push(item); // Push theo thứ tự top->bottom của stack gốc
}
// Kết quả: newStack có thứ tự giống stack gốc

Các constructor của Stack<T>

Constructor Mô tả
Stack<T>() Rỗng, capacity mặc định
Stack<T>(int capacity) Chỉ định capacity ban đầu
Stack<T>(IEnumerable<T>) Tạo từ collection khác

Lưu ý

  • Stack<T> là generic, type-safe, trong System.Collections.Generic
  • Non-generic Stack trong System.Collections cũng có constructor tương tự
  • ToArray() trả về mảng với phần tử top ở index 0
  • foreach trên Stack duyệt từ top xuống bottom
  • Khuyến nghị dùng Stack<T> generic thay vì non-generic