รายการทิศทางเดียวแบบวัฏจักร รายการวัฏจักร (วงกลม) การใช้งานรายการวนซ้ำที่เชื่อมโยงกัน

แต่ละโหนดของรายการแบบวงกลม (CCL) แบบทิศทางเดียว (เชื่อมโยงแบบเดี่ยว) มีฟิลด์ตัวชี้หนึ่งฟิลด์ไปยังโหนดถัดไป ฟิลด์ตัวชี้โหนดสุดท้ายมีที่อยู่ขององค์ประกอบรูท

โหนด OCN สามารถแสดงเป็นโครงสร้างที่คล้ายกับรายการเชิงเส้นที่เชื่อมโยงอย่างเดียว

รายการโครงสร้าง
{
ฟิลด์ int; // data field
รายการโครงสร้าง * ptr; // ชี้ไปที่องค์ประกอบถัดไป
};

การดำเนินการหลักที่ดำเนินการกับองค์ประกอบของ OCP:

  • การเริ่มต้นรายการ
  • การเพิ่มโหนดในรายการ
  • การลบโหนดออกจากรายการ
  • กำลังแสดงรายการ
  • การสลับสองโหนดรายการ

เนื่องจากรายการเป็นแบบวงกลม จึงไม่จำเป็นต้องใช้ฟังก์ชันแยกต่างหากเพื่อลบรากของรายการ

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

1
2
3
4
5
6
7
8
9

รายการโครงสร้าง * init (int a) // a- ค่าของโหนดแรก
{
รายการโครงสร้าง * lst;
// จัดสรรหน่วยความจำสำหรับรูทของรายการ
lst = (รายการโครงสร้าง *) malloc (ขนาดของ (รายการโครงสร้าง));
lst-> ฟิลด์ = a;
lst-> ptr = lst; // ชี้ไปที่รูทโหนดเอง
กลับ (lst);
}

การเพิ่มโหนดให้กับbcc

ฟังก์ชันสำหรับเพิ่มโหนดในรายการรับสองอาร์กิวเมนต์:

  • ชี้ไปที่องค์ประกอบหลังจากที่มีการบวกเกิดขึ้น
  • ข้อมูลสำหรับรายการที่เพิ่ม

ขั้นตอนการเพิ่มองค์ประกอบสามารถแสดงในไดอะแกรมต่อไปนี้:


การเพิ่มรายการไปยัง OCP มีขั้นตอนต่อไปนี้:

  • การสร้างโหนดที่เพิ่มและกรอกข้อมูลลงในช่องข้อมูล
  • การรีเซ็ตตัวชี้ของโหนดก่อนหน้าโหนดที่เพิ่มไปยังโหนดที่เพิ่ม
  • การตั้งค่าตัวชี้ของโหนดที่เพิ่มไปยังโหนดถัดไป (โหนดที่โหนดก่อนหน้าชี้ไป)

ดังนั้น หน้าที่ของการเพิ่มโหนดไปยัง ODC มีรูปแบบที่คล้ายคลึงกับฟังก์ชันของการเพิ่มโหนดในรายการเชิงเส้นที่เชื่อมต่ออย่างง่าย:

1
2
3
4
5
6
7
8
9
10

struct list * addelem (รายการ * lst, หมายเลข int)
{
รายการโครงสร้าง * ชั่วคราว * p;
temp = (รายการโครงสร้าง *) malloc (ขนาดของ (รายการ));
p = lst-> ptr; // บันทึกตัวชี้ไปยังองค์ประกอบถัดไป
lst-> ptr = อุณหภูมิ; // โหนดก่อนหน้าชี้ไปที่ที่สร้างขึ้นใหม่
temp-> field = จำนวน; // บันทึกฟิลด์ข้อมูลของโหนดที่เพิ่มเข้ามา
อุณหภูมิ -> ptr = p; // โหนดที่สร้างขึ้นชี้ไปที่องค์ประกอบถัดไป
กลับ (ชั่วคราว);
}

ค่าที่ส่งกลับของฟังก์ชันคือที่อยู่ของโหนดที่เพิ่มเข้ามา

การลบโหนด OCN

ตัวชี้ไปยังโหนดที่ถูกลบจะถูกส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชันสำหรับการลบโหนด ODC เนื่องจากรายการเป็นแบบวงกลม ไม่จำเป็นต้องส่งตัวชี้ไปที่รูทของรายการ

ฟังก์ชันจะส่งกลับตัวชี้ไปยังโหนดตามหลังที่ถูกลบ

การลบโหนดสามารถแสดงโดยไดอะแกรมต่อไปนี้:

การลบโหนด OTS มีขั้นตอนต่อไปนี้:

  • การตั้งค่าตัวชี้ของโหนดก่อนหน้าไปยังโหนดหลังโหนดที่ถูกลบ
  • การเพิ่มหน่วยความจำของโหนดที่ถูกลบ

1
2
3
4
5
6
7
8
9
10
11
12

struct list * deletelem (รายการ * lst)
{
รายการโครงสร้าง * ชั่วคราว;
อุณหภูมิ = lst;
ในขณะที่ (temp-> ptr! = lst) // สำรวจรายการโดยเริ่มต้นที่รูท
{ // จนกว่าเราจะพบโหนดก่อน lst
temp = temp-> ptr;
}
temp-> ptr = lst-> ptr; // จัดเรียงตัวชี้ใหม่
ฟรี (lst); // เพิ่มหน่วยความจำของโหนดที่ถูกลบ
กลับ (ชั่วคราว);
}

การแสดงองค์ประกอบของ OCP

หน้าที่ของการแสดงองค์ประกอบของ ODS นั้นคล้ายคลึงกับฟังก์ชันสำหรับ OLS ยกเว้นเงื่อนไขของการสิ้นสุดของการข้ามผ่านขององค์ประกอบ
ตัวชี้ไปยังรูทของรายการจะถูกส่งผ่านเป็นอาร์กิวเมนต์ไปยังฟังก์ชันการแสดงองค์ประกอบ
ฟังก์ชันจะข้ามโหนดทั้งหมดตามลำดับและแสดงค่าของโหนด

1
2
3
4
5
6
7
8
9

รายการเป็นโมฆะ (รายการ * lst)
{
รายการโครงสร้าง * p;
p = lst;
ทำ (
printf ("% d", p-> ฟิลด์); // ส่งออกค่าของโหนด p
p = p-> ptr; // ไปที่โหนดถัดไป
) ในขณะที่ (p! = lst); // เงื่อนไขสำหรับการสิ้นสุดการข้ามผ่าน
}

สำหรับ ODCs คุณยังสามารถเรียกใช้ฟังก์ชันการแสดงรายการโดยเริ่มจากโหนดใดก็ได้

การแลกเปลี่ยนของโหนด bcc

เป็นอาร์กิวเมนต์ ฟังก์ชันการแลกเปลี่ยน OCD ใช้ตัวชี้สองตัวสำหรับโหนดที่แลกเปลี่ยน เช่นเดียวกับตัวชี้ไปยังรากของรายการ ฟังก์ชันส่งคืนที่อยู่ของโหนดรูทของรายการ

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

  • โหนดที่ถูกแทนที่คือเพื่อนบ้าน
  • โหนดที่จะแทนที่ไม่ใช่เพื่อนบ้านนั่นคือมีองค์ประกอบอย่างน้อยหนึ่งรายการระหว่างพวกเขา

เมื่อทำการเปลี่ยนโหนดที่อยู่ติดกัน การติดตั้งพอยน์เตอร์ใหม่จะมีลักษณะดังนี้:


เมื่อแทนที่โหนดที่ไม่ได้อยู่ติดกัน การติดตั้งตัวชี้ใหม่จะมีลักษณะดังนี้:

เมื่อติดตั้งพอยน์เตอร์ใหม่ ไม่จำเป็นต้องตรวจสอบโหนดรูท (ตรงกันข้ามกับฟังก์ชันที่คล้ายกันสำหรับ lst2-> ptr = lst1;
lst1-> ptr = ถัดไป2;
ก่อนหน้า1-> ptr = lst2;
}
อื่นถ้า (lst1 == next2)
{
// สลับโหนดข้างเคียง
lst1-> ptr = lst2;
lst2-> ptr = next1;
ก่อนหน้า2-> ptr = lst2;
}
อื่น
{
// โหนดที่เว้นระยะถูกแลกเปลี่ยน
ก่อนหน้า1-> ptr = lst2;
lst2-> ptr = next1;
ก่อนหน้า2-> ptr = lst1;
lst1-> ptr = ถัดไป2;
}
ถ้า (lst1 == หัว)
กลับ (lst2);
ถ้า (lst2 == หัว)
ผลตอบแทน (lst1);
กลับ (หัว);
}

หมายเหตุ: การบรรยายกล่าวถึงคำจำกัดความ วิธีการประกาศ การเริ่มต้น และคุณลักษณะของการใช้งานในการแก้ปัญหาของรายการแบบวงกลม สำรับ ต้นไม้สีแดง-ดำ ตัวอย่างการแก้ปัญหาสำหรับการประมวลผลรายการวงแหวน สำรับ ต้นไม้สีแดง-ดำ

วัตถุประสงค์ของการบรรยาย: เรียนรู้อัลกอริทึมและเทคนิคในการทำงานกับ โครงสร้างข้อมูลแบบไดนามิก, เรียนรู้วิธีแก้ปัญหาโดยใช้โครงสร้างข้อมูลแบบไดนามิกและอัลกอริธึมสำหรับการทำงานกับพวกมันใน C ++

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

โดยใช้ ประเภทโครงสร้าง, พอยน์เตอร์ และ ตัวแปรไดนามิกคุณสามารถสร้างโครงสร้างหน่วยความจำแบบไดนามิกได้หลากหลาย คุณสมบัติของพอยน์เตอร์ในภาษา C ++ อนุญาตให้สร้างโครงสร้างหน่วยความจำแบบไดนามิกตามสแตติก ประกาศตัวแปรหรือส่วนผสมของสถิตและ ตัวแปรไดนามิก... แนวคิดในการจัดระเบียบโครงสร้างแบบไดนามิกทั้งหมดนั้นเหมือนกัน มีการกำหนดประเภทโครงสร้าง S บางฟิลด์ ฟิลด์หนึ่งฟิลด์หรือมากกว่านั้นถูกประกาศตัวชี้ไปยังประเภทโครงสร้างเดียวกันหรือบางฟิลด์ โปรแกรมประกาศตัวแปร d ของประเภท S หรือตัวแปรของตัวชี้ประเภทไปยัง S ในกรณีของการสร้างโครงสร้างแบบไดนามิกทั้งหมด ชื่อของตัวแปรนี้ระหว่างการทำงานของโปรแกรมถูกใช้เป็นชื่อของ "รูท" (ชื่อพาเรนต์) ของโครงสร้างไดนามิก เมื่อรันโปรแกรมในขณะที่กำลังสร้างโครงสร้างไดนามิก ตัวแปรไดนามิกของประเภทที่สอดคล้องกันและเชื่อมโยงโดยการอ้างอิงโดยเริ่มจากตัวแปร d หรือตัวแรก ตัวแปรไดนามิก, ตัวชี้ซึ่งมีอยู่ในตัวแปร d. วิธีนี้ช่วยให้คุณสร้างโครงสร้างแบบไดนามิกด้วยโทโพโลยีใดก็ได้

รายการวนรอบ (วงกลม)

รายการวัฏจักร (วงกลม)- มัน โครงสร้างข้อมูลซึ่งเป็นลำดับขององค์ประกอบ องค์ประกอบสุดท้ายที่มีตัวชี้ไปยังองค์ประกอบแรกของรายการ และองค์ประกอบแรก (ในกรณี แบบสองทิศทางรายการ) - จนถึงรายการสุดท้าย

คุณลักษณะหลักขององค์กรนี้คือไม่มีองค์ประกอบในรายการนี้ที่มีพอยน์เตอร์ว่าง ดังนั้นจึงไม่สามารถเลือกองค์ประกอบที่รุนแรงได้

รายการวัฏจักรเช่นเดียวกับรายการเชิงเส้นเป็นทิศทางเดียวและ แบบสองทิศทาง.

คล้ายกับรายการเชิงเส้นและทิศทางเดียว แต่องค์ประกอบสุดท้ายมีตัวชี้ที่เชื่อมโยงไปยังองค์ประกอบแรก (รูปที่ 32.1)

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


ข้าว. 32.1.

การดำเนินการพื้นฐานที่ดำเนินการด้วยรายการทิศทางเดียวแบบวงกลม:

  • การสร้างรายการ;
  • พิมพ์ (ดู) รายการ;
  • การแทรกรายการลงในรายการ
  • การลบรายการจากรายการ;
  • ค้นหารายการในรายการ;
  • ตรวจสอบว่ารายการว่างเปล่าหรือไม่
  • การลบรายการ

เพื่ออธิบายอัลกอริธึมสำหรับการดำเนินการพื้นฐานเหล่านี้ เราจะใช้การประกาศเดียวกันกับรายการเชิงเส้นเดียวแบบทิศทางเดียว

ให้เรานำเสนอฟังก์ชันของการดำเนินการพื้นฐานที่แสดงไว้เมื่อทำงานกับรายการแบบวนรอบทิศทาง

// สร้างรายการวัฏจักรทิศทางเดียว void Make_Circle_Single_List (int n, Circle_Single_List ** Head, Circle_Single_List * Loop) (ถ้า (n> 0) ((* Head) = new Circle_Single_List (); // จัดสรรหน่วยความจำสำหรับองค์ประกอบใหม่ if ( วน = = NULL) วน = (* หัว); cout<< "Введите значение "; cin >> (* หัว) -> ข้อมูล; // ป้อนค่าของฟิลด์ข้อมูล (* Head) -> Next = NULL; // การทำให้ฟิลด์ที่อยู่เป็นศูนย์ Make_Circle_Single_List (n-1, & ((* Head) -> Next), Loop); ) อื่น ((* หัว) = วนซ้ำ;)) // การพิมพ์รายการแบบวนรอบทิศทางเดียวเป็นโมฆะ Print_Circle_Single_List (Circle_Single_List * หัว) (Circle_Single_List * ptr = Head; // ตัวชี้เสริมทำ (cout<< ptr->ข้อมูล<< "\t"; ptr=ptr-> << "\n"; } /*вставка элемента после заданного номера в циклический однонаправленный список*/ Circle_Single_List* Insert_Item_Circle_Single_List(Circle_Single_List* Head, int Number, int DataItem){ Circle_Single_List *Current = Head; //встали на первый элемент Circle_Single_List *NewItem = new(Circle_Single_List); //создали новый элемент NewItem->ข้อมูล = รายการข้อมูล; if (Head == NULL) (// รายการว่างเปล่า NewItem-> Next = NewItem; Head = NewItem;) else (// รายการไม่ว่างเปล่าสำหรับ (int i = 1; i< Number; i++) Current = Current->ถัดไป; NewItem-> Next = ปัจจุบัน -> ถัดไป; ปัจจุบัน -> ถัดไป = NewItem; ) กลับหัว; ) / * การลบรายการที่มีหมายเลขที่ระบุจากรายการแบบวนรอบทิศทางเดียว * / Circle_Single_List * Delete_Item_Circle_Single_List (Circle_Single_List * Head, int Number) (if (Head! = NULL) (Circle_Single_List * Current = Head; if (Head->< Number; i++) Current = Current->ถัดไป; Circle_Single_List * ptr = หัว; ในขณะที่ (ptr-> ถัดไป! = ปัจจุบัน) ptr = ptr-> ถัดไป; // ลบองค์ประกอบโดยตรง ptr-> Next = Current-> Next; ถ้า (หัว = ปัจจุบัน) หัว = ปัจจุบัน -> ถัดไป; ลบ (ปัจจุบัน); ) อื่น (Head = NULL; ลบ (ปัจจุบัน);)) กลับหัว; ) // ค้นหารายการในบูลรายการทิศทางเดียวแบบวงกลม Find_Item_Circle_Single_List (Circle_Single_List * Head, int DataItem) (Circle_Single_List * ptr = Head; // ตัวชี้เสริมทำ (ถ้า (DataItem == ptr-> Data) คืนค่าจริง; else ptr = ptr- > ถัดไป;) ในขณะที่ (ptr! = Head); return false;) // ตรวจสอบความว่างเปล่าของบูลรายการทิศทางเดียวแบบวงกลม Empty_Circle_Single_List (Circle_Single_List * Head) (ส่งคืน (Head! = NULL? False: true);) // การลบรายการทิศทางเดียวแบบวงกลม void Delete_Circle_Single_List (Circle_Single_List * Head) (if (Head! = NULL) (Head = Delete_Item_Circle_Single_List (Head, 1); Delete_Circle_Single_List (Head);)) รายการ 1

ดูเหมือนรายการเชิงเส้นสองทิศทาง แต่รายการใดๆ มีตัวชี้สองตัว ตัวหนึ่งชี้ไปที่รายการถัดไปในรายการ และอีกตัวชี้ไปที่รายการก่อนหน้า (รูปที่ 32.2)


ข้าว. 32.2.

การดำเนินการขั้นพื้นฐานที่ดำเนินการด้วยวัฏจักร แบบสองทิศทางรายการ:

  • การสร้างรายการ;
  • พิมพ์ (ดู) รายการ;
  • การแทรกรายการลงในรายการ
  • การลบรายการจากรายการ;
  • ค้นหารายการในรายการ
  • ตรวจสอบว่ารายการว่างเปล่าหรือไม่
  • การลบรายการ

เพื่ออธิบายอัลกอริทึมสำหรับการดำเนินการพื้นฐานเหล่านี้ เราจะใช้การประกาศเดียวกันกับเชิงเส้น แบบสองทิศทางรายการ.

ให้เรานำเสนอฟังก์ชันของการดำเนินการพื้นฐานที่ระบุไว้เมื่อทำงานกับ cyclic แบบสองทิศทางรายการ.

// สร้างรายการแบบสองทิศทางแบบวนซ้ำ Circle_Double_List * Make_Circle_Double_List (int n, Circle_Double_List ** หัว, Circle_Double_List * วน) (Circle_Double_List * ptr; // ตัวชี้เสริมถ้า (n> 0) ((* หัว) = ใหม่ Circle_Double_List (); / / จัดสรรหน่วยความจำสำหรับองค์ประกอบใหม่หาก (Loop == NULL) Loop = (* Head); cout<< "Введите значение "; cin >> (* หัว) -> ข้อมูล; // ป้อนค่าของฟิลด์ข้อมูล (* Head) -> Next = NULL; // การทำให้ฟิลด์ที่อยู่เป็นศูนย์ ptr = Make_Circle_Double_List (n-1, & ((* Head) -> Next), Loop); if ((* Head) -> Next! = NULL) (* Head) -> Next-> Prior = (* Head); ถ้า ((* หัว) -> ก่อนหน้า == NULL) (* หัว) -> ก่อนหน้า = ptr; ถ้า (ptr == NULL) ส่งคืน * หัว; อื่นส่งคืน ptr; ) else ((* Head) = Loop; return NULL;)) // การพิมพ์รายการแบบสองทิศทางแบบวนเป็นโมฆะ Print_Circle_Double_List (Circle_Double_List * Head) (Circle_Double_List * ptr = Head; // ตัวชี้เสริมทำ (cout<< ptr->ข้อมูล<< "\t"; ptr=ptr->ถัดไป; ) ในขณะที่ (ptr! = หัว); ศาล<< "\n"; } /*вставка элемента после заданного номера в циклический двунаправленный список*/ Circle_Double_List* Insert_Item_Circle_Double_List (Circle_Double_List* Head, int Number, int DataItem){ Circle_Double_List *Current = Head; //встали на первый элемент Circle_Double_List *NewItem = new(Circle_Double_List); //создали новый элемент NewItem->ข้อมูล = รายการข้อมูล; if (Head == NULL) (// รายการว่างเปล่า NewItem-> Next = NewItem; NewItem-> Prior = NewItem; Head = NewItem;) else (// รายการไม่ว่างเปล่าสำหรับ (int i = 1; i< Number; i++) Current = Current->ถัดไป; NewItem-> Next = ปัจจุบัน -> ถัดไป; ปัจจุบัน -> ถัดไป = NewItem; NewItem-> ก่อนหน้า = ปัจจุบัน; NewItem-> Next-> ก่อนหน้า = NewItem; ) กลับหัว; ) / * การลบรายการด้วยหมายเลขที่กำหนดจากรายการแบบสองทิศทางแบบวนซ้ำ * / Circle_Double_List * Delete_Item_Circle_Double_List (Circle_Double_List * Head, int Number) (if (Head! = NULL) (Circle_Double_List * Current = Head; if (Head-> Next! = หัว) (สำหรับ (int i = 1; i< Number; i++) Current = Current->ถัดไป; Circle_Double_List * ptr = ปัจจุบัน -> ถัดไป; ปัจจุบัน -> ก่อนหน้า -> ถัดไป = ปัจจุบัน -> ถัดไป; ปัจจุบัน -> ถัดไป -> ก่อนหน้า = ปัจจุบัน -> ก่อนหน้า; if (Head = Current) // ลบ Head แรก = Current-> Next; ลบ (ปัจจุบัน); ) อื่น (Head = NULL; ลบ (ปัจจุบัน);)) กลับหัว; ) // ค้นหารายการในบูลรายการแบบสองทิศทางแบบวนรอบ Find_Item_Circle_Double_List (Circle_Double_List * Head, int DataItem) (Circle_Double_List * ptr = Head; // ตัวชี้เสริมทำ (ถ้า (DataItem == ptr-> Data) คืนค่าจริง; else ptr = ptr- > Next;) while (ptr! = Head); return false;) // ตรวจสอบว่ารายการแบบสองทิศทางแบบวงกลมว่างเปล่าหรือไม่ Empty_Circle_Double_List (Circle_Double_List * Head) (return (Head! = NULL? False: true);) / / ลบรายการแบบสองทิศทางแบบวงกลม void Delete_Circle_Double_List (Circle_Double_List * Head) (ถ้า (Head! = NULL) (Head = Delete_Item_Circle_Double_List (Head, 1); Delete_Circle_Double_List (Head);)) รายการ 2.

ปรับปรุงล่าสุด: 25.10.2016

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

ตัวอย่างเช่น หากรายการของเราประกอบด้วยองค์ประกอบหลักหนึ่งรายการ เราสามารถปิดรายการดังกล่าวได้ดังนี้:

Head.next = หัว;

สำหรับการนำไปปฏิบัติ ลองใช้คลาสขององค์ประกอบที่ใช้ในรายการที่เชื่อมโยงอย่างเดียว:

โหนดคลาสสาธารณะ (โหนดสาธารณะ (ข้อมูล T) (ข้อมูล = ข้อมูล;) ข้อมูล T สาธารณะ (รับ; ชุด;) โหนดสาธารณะ ถัดไป (get; set;))

ตอนนี้ มากำหนดคลาสของรายชื่อเสียงเรียกเข้า:

การใช้ System.Collections; ใช้ System.Collections.Generic; เนมสเปซ SimpleAlgorithmsApp (คลาสสาธารณะ CircularLinkedList : IEnumerable // รายการเชื่อมโยงแบบวงกลม (โหนด ศีรษะ; // หัว / องค์ประกอบแรกของโหนด หาง; // สุดท้าย / หางองค์ประกอบจำนวน int; // จำนวนองค์ประกอบในรายการ // เพิ่มองค์ประกอบที่เป็นโมฆะสาธารณะ เพิ่ม (ข้อมูล T) (โหนด โหนด = โหนดใหม่ (ข้อมูล); // ถ้ารายการว่างเปล่าถ้า (หัว == null) (หัว = โหนด; หาง = โหนด; tail.Next = หัว;) อื่น ๆ (โหนดถัดไป = หัว; tail.Next = โหนด; หาง = โหนด;) นับ ++; ) บูลสาธารณะ ลบ (ข้อมูล T) (โหนด ปัจจุบัน = หัว; โหนด ก่อนหน้า = null; ถ้า (IsEmpty) คืนค่าเท็จ do (if (current.Data.Equals (data))) (// ถ้าโหนดอยู่ตรงกลางหรือท้ายสุด if (ก่อนหน้า! = null) (// ลบโหนดปัจจุบัน ตอนนี้ Previous หมายถึงไม่ปัจจุบัน แต่ เป็น current.Next Previous .Next = current.Next; // หากโหนดเป็นโหนดสุดท้าย // เปลี่ยนตัวแปร tail if (current == tail) tail = Previous;) else // หากองค์ประกอบแรกถูกลบ (/ / หากมีเพียงหนึ่งองค์ประกอบในรายการ if (count = = 1) (head = tail = null;) else (head = current.Next; tail.Next = current.Next;)) count--; คืนค่าจริง; ) ก่อนหน้า = ปัจจุบัน ปัจจุบัน = ปัจจุบัน ถัดไป;) ในขณะที่ ( ปัจจุบัน! = หัว); คืนค่าเท็จ; ) สาธารณะ int Count (รับ (จำนวนคืน;)) บูลสาธารณะ IsEmpty (รับ (จำนวนคืน == 0;)) โมฆะสาธารณะ ล้าง () (หัว = null; หาง = null; นับ = 0;) บูลสาธารณะประกอบด้วย (T ข้อมูล) (โหนด ปัจจุบัน = หัว; ถ้า (ปัจจุบัน == null) คืนค่าเท็จ; do (if (current.Data.Equals (data))) คืนค่า true; current = current.Next;) ในขณะที่ (current! = head); คืนค่าเท็จ; ) IEnumerator IEnumerable.GetEnumerator () (ส่งคืน ((IEnumerable) นี้) .GetEnumerator ();) IEnumerator จำนวน .GetEnumerator () (โหนด ปัจจุบัน = หัว; ทำ (ถ้า (ปัจจุบัน! = null) (ผลตอบแทนปัจจุบันข้อมูล; ปัจจุบัน = current.Next;)) ในขณะที่ (ปัจจุบัน! = หัว); )))

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

โมฆะสาธารณะ เพิ่ม (ข้อมูล T) (โหนด โหนด = โหนดใหม่ (ข้อมูล); // ถ้ารายการว่างเปล่าถ้า (หัว == null) (หัว = โหนด; หาง = โหนด; tail.Next = หัว;) อื่น ๆ (โหนดถัดไป = หัว; tail.Next = โหนด; หาง = โหนด;) นับ ++; )

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

บูลสาธารณะ ลบ (ข้อมูล T) (โหนด ปัจจุบัน = หัว; โหนด ก่อนหน้า = null; ถ้า (IsEmpty) คืนค่าเท็จ do (if (current.Data.Equals (data))) (// ถ้าโหนดอยู่ตรงกลางหรือท้ายสุด if (ก่อนหน้า! = null) (// ลบโหนดปัจจุบัน ตอนนี้ Previous หมายถึงไม่ปัจจุบัน แต่ เป็น current.Next Previous .Next = current.Next; // หากโหนดเป็นโหนดสุดท้าย // เปลี่ยนตัวแปร tail if (current == tail) tail = Previous;) else // หากองค์ประกอบแรกถูกลบ (/ / หากมีเพียงหนึ่งองค์ประกอบในรายการ if (count = = 1) (head = tail = null;) else (head = current.Next; tail.Next = current.Next;)) count--; คืนค่าจริง; ) ก่อนหน้า = ปัจจุบัน ปัจจุบัน = ปัจจุบัน ถัดไป;) ในขณะที่ ( ปัจจุบัน! = หัว); คืนค่าเท็จ; )

แอพลิเคชันของรายชื่อแหวน:

หนังสือเวียนLinkedList circularList = ใหม่ CircularLinkedList (); circularList.Add ("ทอม"); circularList.Add ("บ๊อบ"); circularList.Add ("อลิซ"); circularList.Add ("แจ็ค"); foreach (รายการ var ใน circularList) (Console.WriteLine (รายการ);) circularList.Remove ("Bob"); Console.WriteLine ("\ n หลังจากลบ: \ n"); foreach (รายการ var ใน circularList) (Console.WriteLine (รายการ);)

เอาต์พุตคอนโซล:

Tom Bob Alice Jack หลังจากการถอด: Tom Alice Jack

หากคุณพบข้อผิดพลาด โปรดเลือกข้อความและกด Ctrl + Enter