Ngăn xếp C# với các ví dụ về Push & Pop

⚡ Tóm tắt thông minh

Trong C#, Stack là một tập hợp thuộc không gian tên System.Collections tuân theo nguyên tắc vào sau ra trước (LIFO), trong đó phương thức Push thêm một phần tử vào đầu và phương thức Pop loại bỏ nó.

  • 📚 Khái niệm LIFO: Ngăn xếp hoạt động giống như một chồng sách, vì vậy phần tử được thêm vào cuối cùng sẽ là phần tử được lấy ra đầu tiên.
  • Đẩy và bật: Phương thức Push thêm một phần tử vào đầu ngăn xếp, còn phương thức Pop loại bỏ và trả về phần tử ở trên cùng đó.
  • 👀 Nhìn trộm, Đếm, Chứa: Phương thức Peek đọc phần tử trên cùng mà không xóa nó, trong khi Count và Contains báo cáo kích thước và số lượng thành viên.
  • 🧪 Ví dụ minh họa: Hai chương trình trên console minh họa cách sử dụng lệnh Push với Count và Contains, sau đó là lệnh Pop, để bạn có thể hiểu. trace theo thứ tự LIFO.
  • 🛠️ Ngăn xếp chung: Ngăn xếp Lớp trong System.Collections.Generic bổ sung tính an toàn kiểu dữ liệu tại thời điểm biên dịch và tránh việc đóng gói (boxing) cho mã C# mới.
  • 🤖 Hỗ trợ AI: GitHub Copilot tạo cấu trúc khung cho các thao tác Stack trong C#, và ML.NET đọc dữ liệu thông qua các tập hợp có kiểu dữ liệu cụ thể thay vì một stack không chung chung.

Ngăn xếp C#

Ngăn xếp trong C# là gì?

Ngăn xếp là một tập hợp trường hợp đặc biệt đại diện cho khái niệm nhập sau ra trước (LIFO). Để hiểu LIFO trước tiên, hãy lấy một ví dụ. Hãy tưởng tượng một chồng sách với mỗi cuốn sách được xếp chồng lên nhau.

Khái niệm nhập sau xuất trước trong trường hợp sách có nghĩa là chỉ có cuốn sách trên cùng mới có thể được lấy ra khỏi chồng sách. Không thể xóa sách ở giữa vì điều đó sẽ làm xáo trộn cài đặt của ngăn xếp.

Do đó trong C#, ngăn xếp cũng hoạt động theo cách tương tự. Các phần tử được thêm vào ngăn xếp, các phần tử này nằm chồng lên nhau. Quá trình thêm một phần tử vào ngăn xếp được gọi là thao tác đẩy. Để xóa một phần tử khỏi ngăn xếp, bạn cũng có thể xóa phần tử trên cùng của ngăn xếp. Hoạt động này được gọi là pop.

Hãy xem xét các hoạt động có sẵn cho bộ sưu tập Stack một cách chi tiết hơn.

Khai báo ngăn xếp

Ngăn xếp được tạo với sự trợ giúp của kiểu Dữ liệu ngăn xếp. Từ khóa “new” được sử dụng để tạo một đối tượng của Stack. Đối tượng sau đó được gán cho biến st.

Stack st = new Stack()

Thêm phần tử vào ngăn xếp

Phương thức đẩy được sử dụng để thêm một phần tử vào ngăn xếp. Cú pháp chung của câu lệnh được đưa ra dưới đây.

Stack.push(element)

Loại bỏ các phần tử khỏi ngăn xếp

Phương thức pop được sử dụng để loại bỏ một phần tử khỏi ngăn xếp. Thao tác pop sẽ trả về phần tử trên cùng của ngăn xếp. Cú pháp chung của câu lệnh được đưa ra dưới đây

 Stack.pop()

Đếm

Thuộc tính này được sử dụng để lấy số lượng phần tử trong Stack. Dưới đây là cú pháp chung của câu lệnh này.

Stack.Count

Thông tin

Phương thức này được sử dụng để kiểm tra xem một phần tử có tồn tại trong Stack hay không. Dưới đây là cú pháp chung của câu lệnh này. Câu lệnh sẽ trả về true nếu phần tử tồn tại, nếu không nó sẽ trả về giá trị false.

Stack.Contains(element)

Bây giờ hãy xem điều này hoạt động ở cấp độ mã. Tất cả các mã được đề cập dưới đây sẽ được ghi vào Ứng dụng giao diện điều khiển. Mã sẽ được ghi vào tệp Program.cs của chúng tôi.

Trong chương trình bên dưới, chúng ta sẽ viết mã để xem cách chúng ta có thể sử dụng các phương pháp nêu trên.

Ví dụ 1: Phương thức Stack.Push()

Trong ví dụ này, chúng ta sẽ thấy

  • Làm thế nào một ngăn xếp được tạo ra.
  • Cách hiển thị các phần tử của ngăn xếp và sử dụng các phương thức Count và Contain.

Ngăn xếp trong C#

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

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Stack st = new Stack();
   st.Push(1);
   st.Push(2);
   st.Push(3);

   foreach (Object obj in st)
   {
    Console.WriteLine(obj);
   }
    Console.WriteLine(); Console.WriteLine();
    Console.WriteLine("The number of elements in the stack " +st.Count);
    Console.WriteLine("Does the stack contain the elements 3 "+st.Contains(3));
    Console.ReadKey();
  }
 }
}

Code Giải trình:-

  1. Bước đầu tiên được sử dụng để khai báo Stack. Ở đây chúng ta khai báo “st” là một biến để chứa các phần tử của ngăn xếp.
  2. Tiếp theo, chúng ta thêm 3 phần tử vào ngăn xếp của mình. Mỗi phần tử được thêm vào thông qua phương thức Push.
  3. Bây giờ vì các phần tử ngăn xếp không thể được truy cập thông qua vị trí chỉ mục như lập danh sách, chúng ta cần sử dụng một cách tiếp cận khác để hiển thị các phần tử của ngăn xếp. Đối tượng (obj) là một biến tạm thời, được khai báo để giữ từng phần tử của ngăn xếp. Sau đó chúng ta sử dụng câu lệnh foreach để duyệt qua từng phần tử của ngăn xếp. Đối với mỗi phần tử ngăn xếp, giá trị được gán cho biến obj. Sau đó, chúng tôi sử dụng lệnh Console.Writeline để hiển thị giá trị cho bàn điều khiển.
  4. Chúng tôi đang sử dụng thuộc tính Count (số đếm) để lấy số phần tử trong ngăn xếp. Thuộc tính này sẽ trả về một số. Sau đó chúng tôi hiển thị giá trị này cho bảng điều khiển.
  5. Sau đó, chúng tôi sử dụng phương thức Chứa để xem liệu giá trị 3 có trong ngăn xếp của chúng tôi hay không. Điều này sẽ trả về giá trị đúng hoặc sai. Sau đó chúng tôi hiển thị giá trị trả về này cho bảng điều khiển.

Nếu mã trên được nhập đúng và chương trình được chạy thì kết quả sau sẽ được hiển thị.

Đầu ra:

Ngăn xếp trong C#

Từ kết quả đầu ra, chúng ta có thể thấy các phần tử của ngăn xếp được hiển thị. Ngoài ra, giá trị True được hiển thị để nói rằng giá trị 3 được xác định trên ngăn xếp.

Lưu ý: Bạn nhận thấy rằng phần tử cuối cùng được đẩy vào ngăn xếp sẽ được hiển thị đầu tiên. Đây là phần tử trên cùng của ngăn xếp. Số lượng phần tử ngăn xếp cũng được hiển thị trong đầu ra.

Ví dụ 2: Phương thức Stack.Pop()

Bây giờ chúng ta hãy xem chức năng "xóa". Chúng ta sẽ thấy đoạn mã cần thiết để loại bỏ phần tử trên cùng khỏi ngăn xếp.

Ngăn xếp trong C#

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

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Stack st = new Stack();
   st.Push(1);
   st.Push(2);
   st.Push(3);
   
   st.Pop();

   foreach (Object obj in st)
   {
    Console.WriteLine(obj);
   }
    Console.ReadKey();
  }
 }
}

Code Giải trình:-

  1. Ở đây chúng tôi chỉ đưa ra phương thức pop được sử dụng để xóa một phần tử khỏi ngăn xếp.

Nếu mã trên được nhập đúng và chương trình được chạy, kết quả sau sẽ được hiển thị.

Đầu ra:

Ngăn xếp trong C#

Chúng ta có thể thấy rằng phần tử 3 đã bị xóa khỏi ngăn xếp.

Phương thức Peek() của Stack trong C#

Các phương thức Push và Pop hoạt động với phần tử trên cùng của ngăn xếp, nhưng đôi khi bạn chỉ cần xem phần tử trên cùng mà không cần xóa nó. Phương thức Peek thực hiện chính xác điều đó. Nó trả về giá trị trên cùng của ngăn xếp trong khi vẫn giữ nguyên tập hợp, điều này hữu ích khi bạn muốn kiểm tra mục tiếp theo trước khi quyết định xóa nó.

Bước 1) Tạo một ngăn xếp và đẩy ba phần tử vào đó, sao cho giá trị 3 nằm ở trên cùng.

Bước 2) Gọi phương thức Peek để đọc phần tử trên cùng, sau đó kiểm tra thuộc tính Count để xác nhận không có gì bị xóa.

using System;
using System.Collections;

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Stack st = new Stack();
   st.Push(1);
   st.Push(2);
   st.Push(3);
   Console.WriteLine(st.Peek());
   Console.WriteLine(st.Count);
   Console.ReadKey();
  }
 }
}

Code Giải trình:-

  1. Một ngăn xếp có tên là st được khai báo, và các giá trị 1, 2 và 3 được cộng lại bằng phương thức Push, do đó 3 trở thành phần tử trên cùng.
  2. Phương thức Peek trả về phần tử trên cùng mà không xóa nó, và thuộc tính Count vẫn báo cáo tổng số phần tử trong ngăn xếp.

Khi chương trình chạy, nó sẽ in ra giá trị đó. 3 từ Peek và sau đó là số đếm 3Điều này chứng tỏ phần tử vẫn còn trên ngăn xếp. Nếu ngăn xếp trống, Peek sẽ ném ra ngoại lệ Invalid.OperationException, vì vậy việc kiểm tra Count trước khi gọi hàm là an toàn.

Ngăn xếp chung trong C#

Các ví dụ trên sử dụng lớp Stack không chung chung từ System.Collections, lưu trữ mọi phần tử dưới dạng một đối tượng. Mã C# hiện đại thường ưu tiên sử dụng Stack chung chung hơn. Lớp này thuộc không gian tên System.Collections.Generic. Nó liên kết ngăn xếp với một kiểu dữ liệu được khai báo duy nhất, do đó trình biên dịch kiểm tra mọi thao tác Push và Pop mà không cần ép kiểu hay đóng gói.

Những lợi ích chính của Stack chung được liệt kê bên dưới.

  • Loại an toàn: Kiểu dữ liệu được cố định tại thời điểm khai báo, do đó chỉ có các giá trị thuộc kiểu đó mới có thể được thêm vào và lỗi sẽ được phát hiện trong quá trình biên dịch.
  • Không được đấm bốc: Các kiểu dữ liệu giá trị như int được lưu trữ trực tiếp, giúp tránh được chi phí đóng gói mà Stack không phải chịu.
  • Người dọn dẹp đọc: Các phương thức Pop và Peek trả về trực tiếp kiểu dữ liệu đã khai báo, vì vậy bạn không cần phải ép kiểu kết quả từ đối tượng.
using System;
using System.Collections.Generic;

namespace DemoApplication
{
 class Program
 {
  static void Main(string[] args)
  {
   Stack<string> st = new Stack<string>();
   st.Push("Java");
   st.Push("Python");
   Console.WriteLine(st.Pop());
   Console.ReadKey();
  }
 }
}

Trong ví dụ này, ngăn xếp được khai báo là Stack. Vì vậy, nó chỉ chấp nhận các giá trị chuỗi. Phương thức Pop trả về một chuỗi trực tiếp và in ra. Python, giá trị cuối cùng được đẩy vào. Đối với bất kỳ dự án mới nào, Stack chung sẽ là Đây là lựa chọn được khuyến nghị.

Sự khác biệt giữa Stack và Queue trong C#

Một chồng và một hàng đợi Cả ngăn xếp và hàng đợi đều là các cấu trúc dữ liệu kiểm soát thứ tự loại bỏ các phần tử, nhưng chúng sử dụng các quy tắc ngược nhau. Ngăn xếp hoạt động theo nguyên tắc vào sau, ra trước (LIFO), trong khi hàng đợi hoạt động theo nguyên tắc vào trước, ra trước (FIFO). Việc lựa chọn đúng loại ngăn xếp sẽ giúp các nhà phát triển khác hiểu rõ ý định của mã nguồn.

Những điểm khác biệt chính được liệt kê dưới đây:

  • Gọi món: Ngăn xếp (stack) loại bỏ phần tử được thêm vào gần đây nhất trước (LIFO), trong khi hàng đợi (queue) loại bỏ phần tử cũ nhất trước (FIFO).
  • Phương pháp: Ngăn xếp sử dụng các thao tác Push và Pop, trong khi hàng đợi sử dụng Enqueue để thêm phần tử và Dequeue để xóa phần tử.
  • Truy cập phần tử cấp cao nhất: Ngăn xếp đọc phần tử tiếp theo bằng phương thức Peek, còn hàng đợi đọc phần tử tiếp theo bằng phương thức Peek từ phía trước.
  • Sử dụng điển hình: Ngăn xếp phù hợp với các tính năng hoàn tác, đánh giá biểu thức và đệ quy. tracTrong khi đó, hàng đợi phù hợp với việc lập lịch, đệm dữ liệu và duyệt theo chiều rộng.

Cả hai loại đều có sẵn ở dạng chung là Stack và xếp hàng trong System.Collections.Generic, vì vậy bạn có được tính an toàn về kiểu dữ liệu với cả hai lựa chọn.

Câu Hỏi Thường Gặp

Gọi hàm Pop hoặc Peek trên một ngăn xếp rỗng sẽ ném ra ngoại lệ Invalid.OperaLỗi tionException. Trước tiên hãy kiểm tra thuộc tính Count, hoặc sử dụng các phương thức chung của Stack là TryPop và TryPeek, chúng sẽ trả về false thay vì ném lỗi khi ngăn xếp không chứa phần tử nào.

Cả Push và Pop đều chạy trong thời gian O(1) không đổi vì chúng chỉ chạm vào đỉnh của ngăn xếp. Khi mảng nội bộ phải mở rộng, thỉnh thoảng Push sẽ thay đổi kích thước của nó, nhưng chi phí trung bình cho mỗi thao tác vẫn không đổi.

Không. Ngăn xếp chỉ hiển thị phần tử trên cùng thông qua các phương thức Peek và Pop, vì vậy nó không có phương thức truy cập chỉ mục như danh sách. Để đọc mọi giá trị, hãy duyệt qua ngăn xếp bằng vòng lặp foreach hoặc sao chép nó bằng phương thức ToArray.

Phương thức Clear loại bỏ mọi phần tử khỏi ngăn xếp trong một lần gọi và đặt lại Count về 0. Để loại bỏ các phần tử từng cái một từ trên cùng, hãy gọi Pop trong một vòng lặp cho đến khi Count đạt đến 0.

Lớp Stack tiêu chuẩn không an toàn cho đa luồng khi nhiều luồng cùng lúc thực hiện các thao tác ghi. Để truy cập đồng thời, hãy sử dụng ConcurrentStack từ System.Collections.Concurrent, lớp này cung cấp các phương thức TryPush và TryPop nguyên tử mà không cần khóa bên ngoài.

Gọi phương thức ToArray để sao chép ngăn xếp vào một mảng mới, được sắp xếp từ trên xuống dưới. Bạn cũng có thể truyền ngăn xếp cho hàm tạo List để xây dựng một danh sách chung trong khi vẫn giữ nguyên cấu trúc ban đầu.ping cùng một thứ tự.

Đúng vậy. GitHub Copilot viết các khai báo Stack, các lệnh Push và Pop, và các vòng lặp foreach từ một đoạn chú thích ngắn hoặc tên phương thức. Nó thường đề xuất phiên bản Stack chung, vì đó là tập hợp được khuyến nghị cho mã C# mới.

Ngăn xếp hiếm khi lưu trữ dữ liệu huấn luyện ML.NET, dữ liệu này được truyền qua các tập hợp có kiểu dữ liệu cụ thể và đường dẫn IDataView. Tuy nhiên, khái niệm ngăn xếp LIFO xuất hiện bên trong các thuật toán học máy để truy xuất dữ liệu ngược.tracvua, tìm kiếm theo chiều sâu và quản lý các lời gọi phương thức đệ quy.

Tóm tắt bài viết này với: