C# Stack พร้อมตัวอย่าง Push & Pop

⚡ สรุปอย่างชาญฉลาด

Stack ใน C# เป็นคอลเลกชันจากเนมสเปซ System.Collections ที่ใช้หลักการเข้าหลังออกก่อน (LIFO) โดยเมธอด Push จะเพิ่มองค์ประกอบเข้าไปที่ด้านบนสุด และเมธอด Pop จะลบองค์ประกอบนั้นออก

  • 📚 แนวคิด LIFO: การจัดเรียงแบบซ้อน (Stack) ทำงานเหมือนการกองหนังสือ ดังนั้นองค์ประกอบสุดท้ายที่ถูกเพิ่มเข้าไปจะเป็นองค์ประกอบแรกที่ถูกนำออกมา
  • กดและเปิด: เมธอด Push จะเพิ่มองค์ประกอบเข้าไปที่ด้านบนสุดของสแต็ก และเมธอด Pop จะลบและส่งคืนองค์ประกอบที่อยู่บนสุดนั้น
  • 👀 แอบดู นับ และพบว่ามี: เมธอด Peek จะอ่านองค์ประกอบบนสุดโดยไม่ลบออก ในขณะที่ Count และ Contains จะรายงานขนาดและสมาชิกภาพ
  • 🧪 ตัวอย่างการใช้งาน: โปรแกรมคอนโซลสองโปรแกรมสาธิตการใช้ Push ร่วมกับ Count และ Contains จากนั้นใช้ Pop เพื่อให้คุณสามารถ... tracลำดับการจัดเรียงแบบ LIFO
  • 🛠️ สแต็กทั่วไป: กองซ้อน คลาสใน System.Collections.Generic เพิ่มความปลอดภัยของประเภทข้อมูลในระหว่างการคอมไพล์ และหลีกเลี่ยงการแปลงประเภทข้อมูลเป็นประเภทอื่น (boxing) สำหรับโค้ด C# ใหม่
  • 🤖 ความช่วยเหลือจากเอไอ: GitHub Copilot สร้างโครงสร้างพื้นฐานสำหรับการดำเนินการ Stack ใน C# และ ML.NET อ่านข้อมูลผ่านคอลเลกชันที่มีประเภทแทนที่จะใช้ Stack ที่ไม่มีเจเนริก

C# สแต็ค

สแต็คใน C # คืออะไร?

สแต็กเป็นคอลเลกชันกรณีพิเศษซึ่งแสดงถึงแนวคิดเข้าก่อนออกก่อน (LIFO) เพื่อทำความเข้าใจ LIFO ก่อน เรามาลองดูตัวอย่างกัน ลองนึกภาพกองหนังสือที่มีหนังสือแต่ละเล่มวางซ้อนกัน

แนวคิดเรื่องเข้าก่อนออกก่อนในกรณีของหนังสือหมายความว่าเฉพาะหนังสือที่อยู่อันดับต้นๆ เท่านั้นที่จะสามารถนำออกจากกองหนังสือได้ ไม่สามารถลบหนังสือออกจากระหว่างนั้นได้ เนื่องจากจะรบกวนการตั้งค่าของสแต็ก

ดังนั้นใน C#สแต็กก็ทำงานในลักษณะเดียวกัน องค์ประกอบจะถูกเพิ่มเข้าไปในสแต็ก โดยองค์ประกอบหนึ่งจะอยู่ด้านบนของอีกองค์ประกอบหนึ่ง กระบวนการเพิ่มองค์ประกอบเข้าไปในสแต็กเรียกว่าการดำเนินการผลัก หากต้องการลบองค์ประกอบออกจากสแต็ก คุณยังสามารถลบองค์ประกอบที่อยู่ด้านบนสุดของสแต็กได้ด้วย การดำเนินการนี้เรียกว่าการป๊อป

มาดูการดำเนินการที่มีให้สำหรับคอลเลกชัน Stack อย่างละเอียดเพิ่มเติม

ประกาศของกอง

สแต็กถูกสร้างขึ้นด้วยความช่วยเหลือของประเภทข้อมูลสแต็ก คำหลัก "ใหม่" ใช้เพื่อสร้างวัตถุของสแต็ก จากนั้นวัตถุจะถูกกำหนดให้กับตัวแปร st

Stack st = new Stack()

การเพิ่มองค์ประกอบลงในสแต็ก

วิธีการพุชใช้เพื่อเพิ่มองค์ประกอบลงในสแต็ก ไวยากรณ์ทั่วไปของคำสั่งได้รับด้านล่าง

Stack.push(element)

การลบองค์ประกอบออกจากสแต็ก

วิธี pop ใช้เพื่อลบองค์ประกอบออกจากสแต็ก การดำเนินการ pop จะส่งคืนองค์ประกอบที่อยู่ด้านบนสุดของสแต็ก ไวยากรณ์ทั่วไปของคำสั่งมีดังต่อไปนี้

 Stack.pop()

นับ

คุณสมบัตินี้ใช้เพื่อรับจำนวนรายการในสแต็ก ด้านล่างนี้คือไวยากรณ์ทั่วไปของคำสั่งนี้

Stack.Count

ประกอบด้วย

วิธีการนี้ใช้เพื่อดูว่ามีองค์ประกอบอยู่ในสแต็กหรือไม่ ด้านล่างนี้คือไวยากรณ์ทั่วไปของคำสั่งนี้ คำสั่งจะคืนค่าเป็นจริงหากมีองค์ประกอบอยู่ มิฉะนั้นจะส่งคืนค่าเท็จ

Stack.Contains(element)

ตอนนี้เรามาดูการทำงานในระดับรหัสกัน โค้ดที่กล่าวถึงด้านล่างทั้งหมดจะถูกเขียนถึงเรา แอปพลิเคชันคอนโซล- รหัสจะถูกเขียนลงในไฟล์ Program.cs ของเรา

ในโปรแกรมด้านล่างเราจะเขียนโค้ดเพื่อดูว่าเราสามารถใช้วิธีการที่กล่าวมาข้างต้นได้อย่างไร

ตัวอย่างที่ 1: วิธี Stack.Push()

ในตัวอย่างนี้เราจะเห็น

  • วิธีสร้างสแต็ก
  • วิธีการแสดงองค์ประกอบของสแต็ก และใช้วิธีการนับและบรรจุ

สแต็กใน 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 คำอธิบาย:-

  1. ขั้นตอนแรกใช้ในการประกาศ Stack ที่นี่เรากำลังประกาศ "st" เป็นตัวแปรเพื่อเก็บองค์ประกอบของสแต็กของเรา
  2. ต่อไปเราจะเพิ่ม 3 องค์ประกอบลงในสแต็กของเรา แต่ละองค์ประกอบจะถูกเพิ่มด้วยวิธี Push
  3. ขณะนี้เนื่องจากไม่สามารถเข้าถึงองค์ประกอบสแต็กผ่านตำแหน่งดัชนีเช่น รายการอาร์เรย์เราจำเป็นต้องใช้วิธีอื่นในการแสดงองค์ประกอบของสแต็ก Object (obj) เป็นตัวแปรชั่วคราวซึ่งได้รับการประกาศให้เก็บแต่ละองค์ประกอบของสแต็ก จากนั้นเราใช้คำสั่ง foreach เพื่อดูแต่ละองค์ประกอบของสแต็ก สำหรับแต่ละองค์ประกอบสแต็ก ค่าจะถูกกำหนดให้กับตัวแปร obj จากนั้นเราใช้คำสั่ง Console.Writeline เพื่อแสดงค่าไปยังคอนโซล
  4. เรากำลังใช้คุณสมบัติการนับ (เซนต์นับ) เพื่อรับจำนวนรายการในสแต็ก คุณสมบัตินี้จะส่งคืนตัวเลข จากนั้นเราจะแสดงค่านี้ไปยังคอนโซล
  5. จากนั้นเราใช้เมธอดประกอบด้วยเพื่อดูว่าค่า 3 มีอยู่ในสแต็กของเราหรือไม่ สิ่งนี้จะส่งกลับค่าจริงหรือเท็จ จากนั้นเราจะแสดงค่าที่ส่งคืนนี้ไปยังคอนโซล

หากป้อนโค้ดด้านบนอย่างถูกต้องแล้วและรันโปรแกรมจะแสดงผลลัพธ์ต่อไปนี้

Output:

สแต็กใน C #

จากผลลัพธ์ เราจะเห็นว่ามีการแสดงองค์ประกอบของสแต็ก นอกจากนี้ ยังแสดงค่า True เพื่อบอกว่าค่า 3 ถูกกำหนดไว้ในสแต็กด้วย

หมายเหตุ:คุณสังเกตเห็นว่าองค์ประกอบสุดท้ายที่ถูกเพิ่มเข้าไปในสแต็กจะแสดงก่อน นี่คือองค์ประกอบที่อยู่ด้านบนสุดของสแต็ก จำนวนองค์ประกอบของสแต็กยังแสดงในผลลัพธ์ด้วย

ตัวอย่างที่ 2: วิธี Stack.Pop()

ตอนนี้เรามาดูฟังก์ชัน "ลบ" กัน เราจะเห็นโค้ดที่จำเป็นในการลบองค์ประกอบบนสุดออกจากสแต็ก

สแต็กใน 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 คำอธิบาย:-

  1. ที่นี่เราเพิ่งออกวิธีการป๊อปซึ่งใช้ในการลบองค์ประกอบออกจากสแต็ก

หากป้อนโค้ดด้านบนถูกต้องแล้วและรันโปรแกรมจะแสดงผลลัพธ์ต่อไปนี้

Output:

สแต็กใน C #

เราจะเห็นว่าองค์ประกอบที่ 3 ถูกลบออกจากสแต็ก

เมธอด StackPeek() ใน C#

เมธอด Push และ Pop ทำงานกับค่าบนสุดของสแต็ก แต่บางครั้งคุณอาจต้องการดูเฉพาะค่าบนสุดโดยไม่ต้องลบออก เมธอด Peek ทำเช่นนั้นได้ มันจะส่งคืนค่าบนสุดของสแต็กโดยไม่เปลี่ยนแปลงคอลเลกชัน ซึ่งมีประโยชน์เมื่อคุณต้องการทดสอบรายการถัดไปก่อนที่จะตัดสินใจลบออก

ขั้นตอน 1) สร้างสแต็กแล้วเพิ่มองค์ประกอบสามตัวลงไป โดยให้ค่า 3 อยู่ด้านบนสุด

ขั้นตอน 2) เรียกใช้เมธอด Peek เพื่ออ่านองค์ประกอบบนสุด จากนั้นตรวจสอบคุณสมบัติ Count เพื่อยืนยันว่าไม่มีสิ่งใดถูกลบออก

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 คำอธิบาย:-

  1. มีการประกาศสแต็กชื่อ st และบวกค่า 1, 2 และ 3 เข้าด้วยกันโดยใช้วิธี Push ทำให้ 3 กลายเป็นองค์ประกอบบนสุด
  2. เมธอด Peek จะส่งคืนองค์ประกอบบนสุดโดยไม่ลบออก และคุณสมบัติ Count ยังคงรายงานจำนวนรายการทั้งหมดในสแต็ก

เมื่อโปรแกรมทำงาน มันจะพิมพ์ค่าออกมา 3 จากพีคแล้วก็การนับ 3ซึ่งพิสูจน์ได้ว่าองค์ประกอบนั้นยังคงอยู่บนสแต็ก หากสแต็กว่างเปล่า Peek จะส่งข้อผิดพลาด Invalid ออกมาOperaเกิดข้อผิดพลาด tionException ดังนั้นจึงควรตรวจสอบจำนวนนับก่อนเรียกใช้ฟังก์ชันเพื่อความปลอดภัย

สแต็กทั่วไป ในภาษา C#

ตัวอย่างข้างต้นใช้คลาส Stack ที่ไม่ใช่แบบเจเนริกจาก System.Collections ซึ่งจัดเก็บทุกองค์ประกอบเป็นอ็อบเจ็กต์ โค้ด C# สมัยใหม่มักนิยมใช้ Stack แบบเจเนริกมากกว่า คลาสจากเนมสเปซ System.Collections.Generic มันผูกสแต็กเข้ากับประเภทที่ประกาศไว้เพียงประเภทเดียว ดังนั้นคอมไพเลอร์จะตรวจสอบทุกการ Push และ Pop และไม่จำเป็นต้องมีการแปลงประเภทหรือ Boxing ใดๆ

ประโยชน์หลักของ Stack ทั่วไป มีรายชื่อดังต่อไปนี้

  • ความปลอดภัยประเภท: ชนิดข้อมูลถูกกำหนดไว้ตั้งแต่การประกาศ ดังนั้นจึงสามารถผลักค่าเข้าไปได้เฉพาะค่าที่มีชนิดข้อมูลนั้นเท่านั้น และจะตรวจจับข้อผิดพลาดได้ในระหว่างการคอมไพล์
  • ห้ามชกมวย: ประเภทค่า เช่น int จะถูกจัดเก็บโดยตรง ซึ่งช่วยหลีกเลี่ยงค่าใช้จ่ายในการแปลงประเภทข้อมูลที่ Stack ที่ไม่ใช่แบบเจเนริกต้องแบกรับ
  • น้ำยาทำความสะอาดเขียนว่า: Pop และ Peek จะคืนค่าประเภทที่ประกาศไว้โดยตรง ดังนั้นคุณจึงไม่ต้องแปลงค่าผลลัพธ์กลับจากอ็อบเจ็กต์
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();
  }
 }
}

ในตัวอย่างนี้ สแต็กถูกประกาศเป็น Stack ดังนั้นจึงรับเฉพาะค่าสตริงเท่านั้น เมธอด Pop จะส่งคืนสตริงโดยตรงและพิมพ์ออกมา Pythonค่าสุดท้ายที่ถูกผลักเข้าไป สำหรับโปรเจกต์ใหม่ใดๆ ก็ตาม สแต็กทั่วไป เป็นตัวเลือกที่แนะนำ

ความแตกต่างระหว่าง Stack และ Queue ใน C#

กองและ คิว ทั้งสองอย่างเป็นโครงสร้างข้อมูลที่ควบคุมลำดับการลบองค์ประกอบ แต่ใช้กฎที่ตรงกันข้าม สแต็กคือข้อมูลเข้าหลังออกก่อน ในขณะที่คิวคือข้อมูลเข้าก่อนออกก่อน การเลือกใช้โครงสร้างข้อมูลที่ถูกต้องจะทำให้เจตนาของโค้ดของคุณชัดเจนสำหรับนักพัฒนาคนอื่นๆ

ความแตกต่างหลักๆ มีดังต่อไปนี้:

  • สั่งซื้อ: โครงสร้างข้อมูลแบบ Stack จะลบองค์ประกอบที่เพิ่มเข้ามาล่าสุดออกก่อน (LIFO) ในขณะที่โครงสร้างข้อมูลแบบ Queue จะลบองค์ประกอบที่เก่าที่สุดออกก่อน (FIFO)
  • วิธีการ: โครงสร้างข้อมูลแบบ Stack ใช้คำสั่ง Push และ Pop ในขณะที่โครงสร้างข้อมูลแบบ Queue ใช้คำสั่ง Enqueue เพื่อเพิ่มข้อมูล และ Dequeue เพื่อลบข้อมูล
  • การเข้าถึงองค์ประกอบระดับบนสุด: โครงสร้างข้อมูลแบบ Stack จะอ่านรายการถัดไปโดยใช้คำสั่ง Peek ส่วนโครงสร้างข้อมูลแบบ Queue จะอ่านรายการถัดไปโดยใช้คำสั่ง Peek จากด้านหน้า
  • การใช้งานทั่วไป: โครงสร้างข้อมูลแบบ Stack เหมาะสำหรับฟังก์ชันยกเลิกการกระทำ การประเมินนิพจน์ และการเรียกซ้ำ tracในขณะที่คิวเหมาะสำหรับการจัดตารางเวลา การบัฟเฟอร์ และการสำรวจแบบกว้าง (breadth-first traversal)

ทั้งสองประเภทมีจำหน่ายในรูปแบบทั่วไปในชื่อ Stack และเข้าคิว ใน System.Collections.Generic คุณจึงได้รับความปลอดภัยของประเภทข้อมูลไม่ว่าจะเลือกแบบใดก็ตาม

คำถามที่พบบ่อย

การเรียกใช้ Pop หรือ Peek บนสแต็กว่างเปล่าจะทำให้เกิดข้อผิดพลาด InvalidOperaเกิดข้อผิดพลาด โปรดตรวจสอบคุณสมบัติ Count ก่อน หรือใช้เมธอด TryPop และ TryPeek ทั่วไปของ Stack ซึ่งจะคืนค่า false แทนที่จะโยนข้อยกเว้นเมื่อ Stack ไม่มีองค์ประกอบใดๆ

ทั้ง Push และ Pop ทำงานโดยใช้เวลาคงที่ O(1) เนื่องจากมีการเข้าถึงเฉพาะส่วนบนสุดของสแต็กเท่านั้น เมื่ออาร์เรย์ภายในจำเป็นต้องขยายขนาด การ Push เป็นครั้งคราวจะช่วยปรับขนาด แต่ต้นทุนเฉลี่ยต่อการดำเนินการยังคงที่

ไม่ สแต็กจะแสดงเฉพาะค่าบนสุดผ่านเมธอด Peek และ Pop เท่านั้น ดังนั้นจึงไม่มีตัวเข้าถึงดัชนีเหมือนกับลิสต์ หากต้องการอ่านค่าทุกค่าในสแต็ก ให้ใช้ลูป foreach เพื่อวนซ้ำ หรือคัดลอกสแต็กโดยใช้เมธอด ToArray

เมธอด Clear จะลบองค์ประกอบทั้งหมดออกจากสแต็กในการเรียกครั้งเดียวและรีเซ็ตค่า Count เป็นศูนย์ หากต้องการลบรายการทีละรายการจากด้านบน ให้เรียกเมธอด Pop ในลูปจนกว่าค่า Count จะเป็นศูนย์

คลาส Stack มาตรฐานไม่ปลอดภัยต่อการเขียนข้อมูลเมื่อมีหลายเธรดทำการเปลี่ยนแปลงพร้อมกัน สำหรับการเข้าถึงพร้อมกัน ให้ใช้ ConcurrentStack จาก System.Collections.Concurrent ซึ่งมีเมธอด TryPush และ TryPop แบบอะตอมิกโดยไม่ต้องใช้ล็อกภายนอก

เรียกใช้เมธอด ToArray เพื่อคัดลอกสแต็กไปยังอาร์เรย์ใหม่ โดยเรียงลำดับจากบนลงล่าง คุณยังสามารถส่งสแต็กไปยังตัวสร้าง List เพื่อสร้างลิสต์ทั่วไปได้ในขณะที่ยังคงรักษาข้อมูลเดิมไว้ping คำสั่งเดียวกัน

ใช่แล้ว GitHub Copilot เขียนการประกาศ Stack, การเรียก Push และ Pop และลูป foreach จากคำอธิบายสั้นๆ หรือชื่อเมธอด โดยมักจะแนะนำ Stack เวอร์ชันทั่วไป เนื่องจากเป็นคอลเลกชันที่แนะนำสำหรับโค้ด C# ใหม่ๆ

โดยทั่วไปแล้ว Stack จะไม่เก็บข้อมูลสำหรับการฝึกอบรม ML.NET ซึ่งข้อมูลจะไหลผ่านคอลเลกชันแบบมีประเภทและไปป์ไลน์ IDataView อย่างไรก็ตาม แนวคิด Stack แบบ LIFO ปรากฏอยู่ในอัลกอริธึมการเรียนรู้ของเครื่องสำหรับการประมวลผลย้อนกลับtracการค้นหาแบบเจาะลึก และการจัดการการเรียกใช้เมธอดแบบเรียกซ้ำ

สรุปโพสต์นี้ด้วย: