Linked List
ในการเขียนโปรแกรมที่มีการจัดการและการใช้ข้อมูลเป็นจำนวนมากเราอาจจะนำ array
มาใช้ ซึ่งปัญหาจากการนำ array มาใช้ก็คือ array
ต้องมีการกำหนดขนาดของ array ก่อน
และจะไม่สามารถเพิ่มหรือลบได้นอกจากนั้น โครงสร้างข้อมูลของ array ยังมีลักษณะที่เรียงลำดับ ถ้าเราได้ใช้ array เก็บข้อมูลของนักเรียน
1000 คนเช่น
Student St[1000];
ถ้าหากคนที่ 200 ลาออกเราจำเป็นที่จะต้องลบข้อมูลคนที่
200 และยังต้องทำการเลื่อนข้อมูลคนที่ 201 ให้มาเป็น 200 และทำการเลื่อนข้อมูลคนที่ 202
ให้มาเป็น 201 จนถึงคนที่ 1000 ให้มาเป็นคนที่ 999 ซึ่งการทำงานตามขั้นตอนที่ว่านี่จะค่อนข้างยุ่งยากและเสียเวลามาก
Linkled
list เป็นอัลกอริทึ่มทางวิทยาศาสตร์ที่จะสามารถแก้ไขปัญหานี้ได้
โดยหลักการทำงานของ Linkled list คือจะให้ Object แต่ละตัวสามารถเชื่อมต่อกันได้โดยที่ Object แต่ละตัวจะมีตัวชี้ของ
Object ที่อยู่ข้างหน้า และถ้าเราต้องการที่จะเพิ่ม Object
ขึ้นมาถ้า Object นั้นอยู่ตำแหน่งสุดท้ายก็ให้เรานำ
Object ตัวสุดท้ายชี้ไปที่ Object นั้นได้เลย
รูปแบบของ Linked listดูได้จากรูปที่ 14-1
รูปที่ 14-1
นอกจากนี้แล้ว Linked list ยังมีความสามารถอีกหลายอย่าง
ในที่นี้จะยังไม่กล่าวถึงการ Insert Object หรือ การ Delete
Object แต่จะกล่าวถึงการใช้ Linked list ในการชี้ไปที่
Object อื่นก่อน
การทำให้ Object สามารถชี้ไปอีก Object หนึ่งโดยใช้ Data Member
ถ้าเราสร้าง class แบบนี้
class
Student
{
private:
int
Age;
public:
int
GetAge(){return Age;}
void
SetAge(int Num1){ Age = Num1;}
Student *StNext;
};
เมื่อเราสร้าง Object ที่มาจาก class Student ขึ้น เราก็สามารถกำหนดให้ Object ของ เราสามารถชี้ไปที่อีก Object หนึ่งได้
เนื่องจากเรามี Pointer *StNext ที่สามารถชี้ไปที่ Object ที่สามารถสร้างมาจาก class
Student ได้
โปรแกรมที่ 14-1 ตัวอย่างการการทำให้
Object สามารถชี้ไปอีก Object หนึ่งโดยใช้
Data Member
Source code
1:#include"iostream.h"
2:class Student
3:{
4: private:
5: int
Age;
6: public:
7: int
GetAge(){return Age;}
8: void
SetAge(int Num1){ Age = Num1;}
9: Student
*StNext;
10:
11:};
12:void ShowData(Student *SS)
13:{
14: cout
<< "Age of Student is " << SS->GetAge() << endl;
15: if
(SS->StNext)ShowData(SS->StNext);
16:}
17:int main()
18:{
19: Student
Miki;
20: Student
Keakai;
21: Student
Bank;
22:
23: Miki.StNext
= &Keakai;
24: Keakai.StNext
= &Bank;
25: Bank.StNext
= 0;
26:
27: Miki.SetAge(30);
28: Keakai.SetAge(20);
29: Bank.SetAge(256);
30:
31: ShowData(&Miki);
32:
33: return 0;
34:}
Output
Age of Student is 30
Age of Student is 20
Age of Student is 256
อธิบาย Source code
โปรแกรมนี้ได้มีการใช้ class Student ซึ่งได้อธิบายมาก่อนหน้านี้แล้ว
บรรทัดที่ 19 ถึง
บรรทัดที่ 21:เป็นการสร้าง Object Miki,Keakai,Bank ที่เป็น class Student
บรรทัดที่ 22 ถึง บรรทัดที่
25:เป็นการใช้ Data Meber St ของ แต่ละ
Object ให้ชี้ไปที่ Object อีกตัวหนึ่งจนถึง
Object สุดท้ายให้ชี้ไปที่ Null แทน
บรรทัดที่ 31:เป็นการใช้ Function
ShowData() ซึ่ง Function นี้จะมีการทำงานคือ
เป็น Function
ที่จะทำการรับที่อยู่ของ Object ประเภท Student
มา จากนั้นจึงทำการแสดงอายุของ Object นั้น
เสร็จแล้วก็จะทำการเช็คว่า Data Member StNext ของ Object
นั้นเท่ากับ 0 หรือไม่ ถ้าเท่ากับ 0 ก็จะไม่ทำอะไรต่อ แต่ถ้าไม่เท่ากับ 0 ก็หมายความว่า StNext
ได้ทำการชี้ไปที่ address ของ Object อื่น ก็ให้ใช้ Function ShowData อีกรอบ
โดยส่งอาร์กิวเมนท์ไปคือ Object ที่โดน Object นี้ชี้อยู่
ในที่นี้หลักการทำงานของ
โปรแกรมคือ
1.ตอนแรกส่งที่อยู่ของ
Miki ไป หลังจากที่โปรแกรมทำการแสดงผลอายุแล้วก็ทำการเช็คว่า Miki ได้ชี้ไปที่ Object อื่นหรือไม่จาก StNext ซึ่งปรากฎว่าจริง ก็ให้ ทำ ShowData() โดยคราวนี้อาร์กิวเมนท์ที่ส่งไปคือ
ที่อยู่ของ Keakai เพราะว่า Miki ชี้ที่
Keakai อยู่
2.ทำการแสดงผลอายุของ
Keakai จากนั้นทำการเช็คว่า Keakai ได้ชี้ไปที่
Object อื่นหรือไม่ ซึ่งปรากฎว่าจริงก็ให้ทำ ShowData
โดยคราวนี้อาร์กิวเมนท์ที่ส่งไปคือ ที่อยู่ของ Bank เพราะว่า Keakai ชี้ที่ Bank อยู่
3. ทำการแสดงผลอายุของ
Bank เนื่องจาก Object Bank ไม่ได้ชี้ไปที่ที่อยู่ของ
Object ใดเลยจึงไม่ต9ต้องทำงานต่อ
การใช้ Member
Function ในการจัดการกับ Object ที่ชี้อยู่
ในโปรแกรมที่ 14-1
เราได้ใช้ Function ShowData ซึ่งเป็น Function
จากภายนอก class คราวนี้เราจะใช้ Function
ShowData ให้เป็น Member Function ที่อยู่ใน class
Student
โปรแกรมที่ 14-2 การใช้ Member
Function ในการจัดการกับ Object ที่ชี้อยู่
Source code
1:#include"iostream.h"
2:class Student
3:{
4: private:
5: int
Age;
6: public:
7: int
GetAge(){return Age;}
8: void
SetAge(int Num1)
9: {
10: Age
= Num1;
11: }
12:
13: Student
*StNext;
14: void
ShowData()
15: {
16: cout
<< "Age of Student is " << this->GetAge() <<
endl;
17: if
(this->StNext) this->StNext->ShowData();
18: }
19:};
20:
21:
22:
23:int main()
24:{
25: Student
Miki;
26: Student
Keakai;
27: Student
Bank;
28:
29: Miki.StNext
= &Keakai;
30: Keakai.StNext
= &Bank;
31: Bank.StNext
= 0;
32:
33: Miki.SetAge(30);
34: Keakai.SetAge(20);
35: Bank.SetAge(256);
36:
37: Miki.ShowData();
38:
39: return 0;
40:}
Output จะเหมือนกับโปรแกรมที่ 14-1
อธิบาย Source code
บรรทัดที่ 14 ถึง
บรรทัดที่ 18:เป็นFunction ShowData ซึ่งจะเห็นได้ว่า
Function นี้จะไม่ต้องมีการส่งอาร์กิวเมนท์ไป แต่การทำงานของ
Function นี้จะขึ้นอยู่กับ ว่า Object ตัวไหนเรียกใช้
และถ้า Object นั้นมีการชี้ไปที่ Object อื่น โปรแกรมก็จะมีการทำงาน ShowData ของ Object
ที่โดยชี้อยู่
การใช้ Linked list ในการ Insert ข้อมูล
ในการที่เราจะใช้
โครงสร้าง Linked list เราจะต้องมี Pointer ที่ทำหน้าที่ชี้ Object ตัวแรกด้วย
โดยปกติเราจะนิยมเรียกว่า Head หรือ First
เราสามารถใช้ Link
list ในการ Insert ข้อมูลได้
ซึ่งจะทำให้ปัญหาในการใช้ array หมดไป โดยอัลกอริทึ่มในการ Insert
ข้อมูลมีดังนี้
การ Insert ข้อมูลที่ตำแหน่งสุดท้าย
1.ให้ Object ตัวสุดท้ายชี้ไปยัง Object ที่ Insert เข้ามา
2.ให้ Object ตัวที่ Insert เข้ามาชี้ไปยัง
Null
ดูได้จากรูปที่
14-2
รูปที่ 14-2 แสดงรูปแบบการ Insert ข้อมูลเข้าไปที่ตำแหน่งสุดท้าย
การ Insert ข้อมูลเข้าไปที่ตำแหน่งแรกสุด
1.ให้ Object ที่ Insert เข้ามาชี้ไปที่
Head ชี้อยู่
2.ให้ Head ชี้ไปที่ Object ที่ Insert
เข้ามา
ดูได้จากรูปที่
14-3
รูปที่ 14-3 แสดงรูปแบบการ Insert ข้อมูลเข้าไปที่ตำแหน่งแรกสุด
การ Insert ข้อมูลที่ตำแหน่งตรงกลาง
1.ให้ Object ที่ Insert เข้ามาชี้ไปที่
Object ที่ตำแหน่งที่ต้องการ
2.ให้ Object ที่อยู่ก่อนหน้าตำแหน่งที่ต้องการ
ชี้ไปที่ Object ที่ Insert เข้ามา
ดูได้จากรูปที่ 14-4
รูปที่ 14-4 แสดงรูปแบบการ Insert ข้อมูลเข้าไปที่ตำแหน่งตรงกลาง
โปรแกรมที่ 14-3 ตัวอย่างการ
Insert ข้อมูลเข้าไปที่ตำแหน่งสุดท้ายใน Linked list
Source code
1:#include"iostream.h"
2:#include"conio.h"
3:class Student
4:{
5: private:
6: int
Age;
7: char
Name[30];
8: public:
9: int
GetAge(){return Age;}
10: void
SetAge(int Num1){ Age = Num1;}
11: Student
*StNext;
12:
13:};
14:Student Head;
15:void ShowData()
16:{
17: Student
*Poi;
18: Poi =
&Head;
19: Poi =
Poi->StNext;
20: while(1==1)
21: {
22: cout
<< "Age of Student is " << Poi->GetAge() <<
endl;
23:
24: if
(Poi->StNext==0)break;
25: Poi
= Poi->StNext;
26: }
27:}
28:
29:void InsertData(Student *SInsert)
30:{
31:
32: Student
*Poi;
33: Poi =
&Head;
34: while(Poi->StNext
!=0)
35: {
36: Poi
=Poi->StNext;
37:
38: }
39:
40:
41: Poi->StNext
= SInsert;
42: SInsert->StNext
=0;
43:}
44:
45:int main()
46:{
47:
48: int
choice;
49: int Age;
50:
51: Student
Miki;
52: Student
Keakai;
53: Student
Bank;
54:
55: Head.StNext
= &Miki;
56: Miki.StNext
= &Keakai;
57: Keakai.StNext
= &Bank;
58: Bank.StNext
= 0;
59:
60: Miki.SetAge(30);
61: Keakai.SetAge(20);
62: Bank.SetAge(256);
63:
64: ShowData();
65: choice =
1;
66:
67: while(1==1)
68: {
69: Student
*SIn = new Student;
70: cout
<< endl;
71: cout
<< " Menu."
<< endl;
72: cout
<< "1.Insert Data " << endl;
73: cout
<< "2.Exit " << endl;
74: cout
<< "Please choose menu:";
75: cin
>> choice;
76: if
(choice != 1)break;
77: cout
<< "Please enter Age :" ;
78: cin
>> Age;
79: SIn->SetAge(Age);
80:
81: InsertData(SIn);
82:
83: clrscr();
84: ShowData();
85: }
86:
87:
88:
89: return 0;
90:}
Output
Age of Student is:30
Age of Student is:20
Age of Student is:256
Menu.
1.Insert Data
2.Exit
Please choose menu:1
Please enter Age :66
เมื่อถึงตรงนี้โปรแกรมจะทำการ Clear หน้าจอ และ แสดงผล
Age of Student is:30
Age of Student is:20
Age of Student is:256
Age of Student is:66
Menu.
1.Insert Data
2.Exit
Please choose menu:2
อธิบาย Source code
บรรทัดที่ 14:เป็นการประกาศให้
Head อยู่ในส่วนของ Global เพื่อที่จะให้ใช้ได้ทั้งโปรแกรม
บรรทัดที่ 55 ถึง
บรรทัดที่ 58:เป็นการให้ Head ชี้ไปที่
Miki และก็เป็นการกำหนดให้ Object แต่ละตัวชี้ไปที่ตัวต่อไปจนถึง
Object Bank ให้ชี้ไปที่ Null แทน
เพราะเป็นตัวสุดท้าย
การทำงานของ Function ShowData ในโปรแกรมนี้
Function
ShowData อยู่ระหว่างบรรทัดที่ 15 ถึง
บรรทัดที่ 27 โดยจะมีการทำงานคือสร้าง Pointer ชื่อ Poi และให้ทำการชี้ไปที่ Head จากนั้นเป็นการกำหนดให้ Poi ชี้ไปที่ Poi->StNext
คือชี้ไปที่ Object ที่ Head ชี้อยู่ แล้วก็ให้ทำการวน loop แสดงผล
โดยมีเงื่อนไขในการออกจาก loop อยู่ในบรรทัดที่ 24: คือ
if (Poi->StNext==0)break; จะเป็นการเช็คว่าถ้าหาก
Object ได้มีการชี้ไปที่ Null จริง
ก็จะถือว่าเป็นตัวสุดท้ายแล้วก็ให้ทำการออกจาก loop แต่ถ้าไม่จริงก็ให้ทำบรรทัดที่
25 คือให้ Poi ทำการชี้ที่ Object
Poi ทำการชี้อยู่ ส่วนสาเหตุที่ในการวน loop while ในบรรทัดที่ 20 ถึงมีเงื่อนไขให้ 1==1 จึงจะทำก็เพราะว่า เป็นเงื่อนไขที่ยังไงก็เป็นจริงอยู่แล้ว
ในโปรแกรมนี้จะปล่อยให้ while ทำงานไปเรื่อยๆ ส่วน Source
code ที่จะทำการออกจาก loop จะอยู่ในบรรทัดที่
24 แทน
ในที่นี้ถ้าหากเราใช้ Function ShowData เมื่อตอนรันโปรแกรมโดย
Head ชี้ไปที่ Miki
Miki ชี้ไปที่ Keakai
Keakai ชี้ไปที่ Bank
Bank ชี้ไปที่ Null
เมื่อเราใช้ Function ShowData ก่อนที่จะถึง loop
while ตัว Poi ก็จะทำการชี้ไปที่ Miki เนื่องจาก Source code
ในบรรทัดที่ 19
รอบแรก ทำการแสดงผลอายุของ Miki จากนั้นก็เช็คเงื่อนไขว่าชี้ไปที่
Null หรือเปล่า ซึ่งปรากฎว่าไม่จริงก็จะให้ Poi ชี้ไปที่ Poi->StNext นั่นคือ Keakai
รอบที่ 2 ทำการแสดงผลอายุของ Keakai จากนั้นก็เช็คเงื่อนไขว่าชี้ไปที่
Null หรือเปล่า ซึ่งปรากฎว่าไม่จริงก็จะให้ Poi ชี้ไปที่ Poi->StNext นั่นคือ Bank
รอบที่ 3 ทำการแสดงผลอายุของ Bank จากนั้นก็เช็คเงื่อนไขว่าชี้ไปที่
Null หรือเปล่า ซึ่งปรากฎว่าจริงก็ให้ออกจาก loop
Function
InsertData ทำงานอย่างไร
Function
InsertData อยู่ในบรรทัดที่ 29 ถึง บรรทัดที่ 43
โดย Function นี้จะมีการับพารามิเตอร์เป็น Pointer
ที่สามารถชี้ไปที่ Object ที่สร้างจาก class
Student ได้ โดยจะมีการทำงานดังนี้
บรรทัดที่ 32 และ บรรทัดที่ 33:สร้าง Poi เพื่อที่จะใช้หา Object ตัวสุดท้าย
บรรทัดที่ 34 ถึง บรรทัดที่ 38:เป็นการวน loop ให้ Poi ชี้ไปที่
Poi->StNext ไปเรื่อยจนกว่า Poi-> จะเท่ากับ
0 ก็จะออกจาก loop(เงื่อนไขของเราคือถ้าไม่เท่ากับ
0 ก็จะทำการวนloop)
บรรทัดที่ 41 ถึง บรรทัดที่ 42:กว่าจะทำงานถึงบรรทัดนี้ ถึงตอนนี้ Poi จะชี้ไปที่ Object
สุดท้ายแล้วการทำงานของ 2 บรรทัดนี้คือ
1.ให้ Object
สุดท้ายทำการชี้ไปที่ Object ที่ Insert
เข้ามา
2.ให้ Object
ตัวที่ Insert เข้ามาทำการชี้ไปที่ Null
โปรแกรมที่ 14-4 ตัวอย่างการ
Insert ข้อมูลโดยมีการระบุตำแหน่ง
Source code
1:#include"iostream.h"
2:#include"conio.h"
3:class Student
4:{
5: private:
6: int
Age;
7: char
Name[30];
8: public:
9: int
GetAge(){return Age;}
10: void
SetAge(int Num1){ Age = Num1;}
11: Student
*StNext;
12:
13:};
14:Student Head;
15:void ShowData()
16:{
17: Student
*Poi;
18: Poi =
&Head;
19: while(1==1)
20: {
21: Poi
= Poi->StNext;
22: cout
<< "Age of Student is " << Poi->GetAge() <<
endl;
23:
24: if
(Poi->StNext==0)break;
25:
26: }
27:}
28:
29:void InsertData(Student *SInsert,int Position)
30:{
31:
32: Student
*Poi;
33: Poi =
&Head;
34: int i=0;
35: while(1==1)
36: {
37: i++;
38: if(i==
Position)break;
39: Poi
= Poi->StNext;
40: }
41:
42: SInsert->StNext
= Poi->StNext;
43: Poi->StNext
= SInsert;
44:
45:}
46:
47:int main()
48:{
49:
50: int
choice;
51: int Age;
52: int
Position;
53:
54: Student
Miki;
55: Student Keakai;
56: Student
Bank;
57:
58: Head.StNext
= &Miki;
59: Miki.StNext
= &Keakai;
60: Keakai.StNext
= &Bank;
61: Bank.StNext
= 0;
62:
63: Miki.SetAge(30);
64: Keakai.SetAge(20);
65: Bank.SetAge(256);
66:
67: ShowData();
68:
69: while(1==1)
70: {
71: Student
*SIn = new Student;
72: cout
<< endl;
73: cout
<< " Menu."
<< endl;
74: cout
<< "1.Insert Data " << endl;
75: cout
<< "2.Exit " << endl;
76: cout
<< "Please choose menu:";
77: cin
>> choice;
78:
79: if
(choice != 1)break;
80:
81: cout
<< "Please enter Age :" ;
82: cin
>> Age;
83: cout
<< "Please enter Position :" ;
84: cin
>> Position;
85:
86: SIn->SetAge(Age);
87:
88: InsertData(SIn,Position);
89:
90: clrscr();
91: ShowData();
92: }
93:
94:
95:
96: return 0;
97:}
Output
Age of Student is:30
Age of Student is:20
Age of Student is:256
Menu.
1.Insert Data
2.Exit
Please choose menu:1
Please enter Age :66
Please enter Position:2
เมื่อถึงตรงนี้โปรแกรมจะทำการ Clear หน้าจอ และ แสดงผล
Age of Student is:30
Age of Student is:66
Age of Student is:20
Age of Student is:256
เพื่อให้เป็นการประหยัดเนื้อที่จะทำการแสดงผลเพียงเท่านี้
อธิบาย Source code
โปรแกรมนี้จะคล้ายกับโปรแกรมที่ 14-3 แต่จะแตกต่างกันที่
Function InsertData จะต้องมีการรับอาร์กิวเมนท์ที่จะกำหนดตำแหน่งที่เราต้องการแทรกข้อมูลด้วย
Function
InsertData อยู่ระหว่างบรรทัดที่ 29 ถึง
บรรทัดที่ 45: โดย Source code ของการหาตำแหน่งที่ต้องการอยู่ในบรรทัดที่
35 ถึง บรรทัดที่ 40 มีหลักการทำงานคือ
ให้ ตัว Poi ชี้ไปที่ Poi->StNext ไปเรื่อยๆในแต่ละรอบ
และในแต่ละรอบก็ให้ตัวแปร i เพื่มอีก 1 และถ้าตัวแปร i เท่ากับ Position จริงก็ให้ออกจาก loop โดยที่ในการเช็คว่า i เท่ากับ Position หรือเปล่าจะทำก่อนที่จะให้ Poi
ชี้ไปที่ Poi->SetNext เมื่อออกจาก loop
Poi ก็จะชี้ไปที่ Object ที่มีตำแหน่งเท่ากับ Position
–1
เช่นถ้าเราส่งอาร์กิวเมนท์ Position เท่ากับ 1
เมื่อมาถึงโปรแกรมก็จะทำการเพิ่มค่าให้กับ i อีก1
จากนั้นจึงทำการเช็คเงื่อนไขว่าเท่ากับ Position จริงหรือเปล่า ซึ่งปรากฎว่าจริงก็ให้ออกจาก loop ไปก่อนโดยที่
Poi ยังไม่ได้ชี้ไปที่ Poi->StNext เลยเท่ากับว่าตอนนี้
Poi ชี้ไปที่ Head ไม่ได้ชี้ไปที่ Object
ที่ 1
จากนั้นจึงทำการกำหนดให้
Sinsert->StNext = Poi.StNext;
ถ้าหาก Poi ชี้ไป Head จริงก็จะมี StNext ชี้ไปที่
Miki จริงก็จะเป็นการกำหนดให้ Object ที่
Insert เข้ามามี StNext ชี้ไปที่ Miki
Poi->StNext = SInsert;
ถ้าหาก Poi ชี้ไปที่ Head จริงก็จะเป็นการกำหนดให้ Head มี StNext ชี้ไปที่ Object ที่
Insert เข้ามา
การ Insert
Object โดยใช้การกำหนดชื่อ
ในกรณีที่ Object
แต่ละตัวของเรามีชื่อเป็นสมาชิกของ Object เราอาจจะใช้
Linked list ในการInsert
Object โดยที่เราจะกำหนดชื่อคนที่เราต้องการไปแทนที่ในตำแหน่งนั้นแทนก็ได้
เช่นข้อมูลมีลักษณะดังนี้
Miki Keakai Bank
แล้วเราต้องการเพิ่ม Object Oak โดยที่เรากำหนดให้ต้องไปแทนที่
บริเวณที่ Miki อยู่ ก็จะเป็นแบบนี้
Oak Miki Keakai Bank
โปรแกรมที่ 14-5 ตัวอย่างการการ
Insert Object โดยใช้การกำหนดชื่อ
Source code
1:#include"iostream.h"
2:#include"conio.h"
3:#include"string.h"
4:class Student
5:{
6: private:
7: int
Age;
8: char
Name[30];
9: public:
10: int
GetAge(){return Age;}
11: void
SetAge(int Num1){ Age = Num1;}
12: char
*GetName(){return Name;}
13: void
SetName(char Na[]){ strcpy(Name,Na);}
14: Student
*StNext;
15:
16:};
17:Student Head;
18:void ShowData()
19:{
20: Student
*Poi;
21: Poi
= &Head;
22: while(1==1)
23: {
24: Poi
= Poi->StNext;
25: cout
<< "Name of Student is " << Poi->GetName() <<
endl;
26:
27: if
(Poi->StNext==0)break;
28:
29: }
30:}
31:
32:void InsertData(Student *SInsert,char
Name[])
33:{
34:
35: Student
*Poi;
36: Poi
= &Head;
37:
38: while(1==1)
39: {
40: Poi = Poi->StNext;
41: if(strcmp(Poi->GetName(),Name)==0)break;
42:
43: }
44:
45: SInsert->StNext
= Poi->StNext;
46: Poi->StNext
= SInsert;
47:}
48:
49:
50:
51:int main()
52:{
53:
54: int
choice;
55: int
Age;
56:
57: char
Name[30];
58: char
Namebefore[30];
59:
60: Student
Miki;
61: Student
Keakai;
62: Student
Bank;
63:
64: Head.StNext
= &Miki;
65: Miki.StNext
= &Keakai;
66: Keakai.StNext
= &Bank;
67: Bank.StNext
= 0;
68:
69: Miki.SetName("Miki");
70: Keakai.SetName("Keakai");
71: Bank.SetName("Bank");
72:
73:
74: ShowData();
75:
76: while(1==1)
77: {
78: Student
*SIn = new Student;
79: cout
<< endl;
80: cout
<< " Menu."
<< endl;
81: cout
<< "1.Insert Data " << endl;
82: cout
<< "2.Exit " << endl;
83: cout
<< "Please choose menu:";
84: cin
>> choice;
85:
86: if
(choice != 1)break;
87:
88: cout
<< "Please enter Name:" ;
89: cin
>> Name;
90: cout
<< "Please enter Name before:" ;
91: cin
>> Namebefore;
92:
93: SIn->SetName(Name);
94:
95: InsertData(SIn,Namebefore);
96:
97: clrscr();
98: ShowData();
99: }
100:
101:
102:
103: return
0;
104:}
Output
Name of Student is Miki
Name of Student is Keakai
Name of Student is Bank
Menu.
1.Insert Data
2.Exit
Please choose menu:1
Please enter Name:Oak
Please enter Name before:Miki
เมื่อมาถึงตรงนี้โปรแกรมจะทำการ
เคลียร์หน้าจอและแสดง
Name of Student is Miki
Name of Student is Oak
Name of Student is Keakai
Name of Student is Bank
เพื่อความประหยัดเนื้อที่จึงขอแสดง Output เพียงเท่านี้
อธิบาย Source code
โปรแกรมนี้ class Student จะมีการใช้ Member
Function ในการกำหนดชื่อ และ การนำชื่อออกมาใช้ด้วยโดย Member
Function นั้นคือ SetName และ GetName ใน Function InsertData จะต้องมีการส่งอาร์กิวเมนท์ชื่อของ
Object ที่เราต้องการให้ไปแทนที่ด้วย
Function InsertDataจะอยู่ระหว่างบรรทัดที่
32 ถึง บรรทัดที่ 47:
การทำงานของ Function
InsertData คือ จะทำการ วน loop เพื่อที่จะให้
Poi ทำการชี้ไปที่ Poi->StNext ไปเรื่อย
ส่วนเงื่อนไขที่จะทำให้ออกจาก loop อยู่ในบรรทัดที่ 41
if(strcmp(Poi->GetName(),Name)==0)break;
เป็นการใช้ Function
strcmp เพื่อที่จะใช้ในการเปรียบเทียบ String 2 String ถ้าหาก 2 String นี้มีค่าเท่ากันค่าที่ได้จาก Function
จะเท่ากับ 0 ซึ่งถ้าเป็นแบบนั้นจริงก็ให้ออกจาก
loop
จากนั้นในบรรทัดที่ 45
และ บรรทัดที่ 46 เป็นการให้ Object ที่ Insert เข้าไปแทรกอยู่ต่อจาก Poi
การนับจำนวนของ Object
ที่สร้างขึ้นมาใน List
ในการใช้ Linked
list เราอาจจะมีความจำเป็นที่จะต้องการทราบจำนวนของ Object ที่มีอยู่ใน list ซึ่งเราอาจจะทำได้โดยเขียนFunction
ขึ้นมาซึ่งจะทำการวน loop เพื่อให้ Pointer
ชี้ไปที่ Object และเช็คว่า Object นั้นชี้ไปที่ Null หรือเปล่าถ้าไม่ใช่ก็ทำการนับ จนกว่าจะใช่ก็ได้
ซึ่งจะทำให้เราทราบจำนวนของ Object ที่อยู่ใน list
โปรแกรมที่ 14-6 ตัวอย่างการสร้าง
Function เพื่อนับจำนวน Object
Source code
1:#include"iostream.h"
2:#include"conio.h"
3:#include"string.h"
4:class Student
5:{
6: private:
7: int
Age;
8: char
Name[30];
9: public:
10: int
GetAge(){return Age;}
11: void
SetAge(int Num1){ Age = Num1;}
12: char
*GetName(){return Name;}
13: void
SetName(char Na[]){ strcpy(Name,Na);}
14: Student
*StNext;
15:
16:};
17:Student Head;
18:
19:int Count()
20:{
21: Student
*Poi;
22: Poi=
&Head;
23: int i=0;
24: while(1==1)
25: {
26: if(Poi->StNext==0)break;
27: i++;
28: Poi
= Poi->StNext;
29: }
30: return i;
31:}
32:void ShowData()
33:{
34: Student
*Poi;
35: Poi =
&Head;
36: while(1==1)
37: {
38: Poi
= Poi->StNext;
39: cout
<< "Name of Student is " << Poi->GetName() <<
endl;
40:
41: if
(Poi->StNext==0)break;
42:
43: }
44: cout
<< " Number of Student is
:" << Count();
45:}
46:
47:void InsertData(Student *SInsert,char Name[])
48:{
49:
50: Student
*Poi;
51: Poi =
&Head;
52: if(strcmp(Name,"")
!=0)
53: {
54: while(1==1)
55: {
56:
57: if(strcmp(Poi->StNext->GetName(),Name)==0)break;
58: Poi = Poi->StNext;
59: }
60:
61: SInsert->StNext
= Poi->StNext;
62: Poi->StNext
= SInsert;
63: }
64: else
65: {
66: Poi->StNext
=SInsert;
67: SInsert->StNext
=0;
68: }
69:
70:}
71:
72:
73:
74:
75:int main()
76:{
77:
78: int
choice;
79:
80:
81: char
Name[30];
82: char
Namebefore[30];
83:
84: Student
Miki;
85: Student
Keakai;
86: Student
Bank;
87:
88: Head.StNext
= &Miki;
89: Miki.StNext
= &Keakai;
90: Keakai.StNext
= &Bank;
91: Bank.StNext
= 0;
92:
93: Miki.SetName("Miki");
94: Keakai.SetName("Keakai");
95: Bank.SetName("Bank");
96:
97:
98: ShowData();
99:
100: while(1==1)
101: {
102: Student
*SIn = new Student;
103: cout
<< endl;
104: cout
<< " Menu."
<< endl;
105: cout
<< "1.Insert Data " << endl;
106: cout
<< "2.Exit " << endl;
107: cout
<< "Please choose menu:";
108: cin
>> choice;
109:
110: if
(choice == 2)break;
111: else
112: {
113: cout
<< "Please enter Name:" ;
114: cin
>> Name;
115: if
(Count()>0)
116: {
117: cout
<< "Please enter Name before:" ;
118: cin
>> Namebefore;
119: }
120: else
121: strcpy(Namebefore,"");
122:
123: SIn->SetName(Name);
124: InsertData(SIn,Namebefore);
125: break;
126: }
127:
128: clrscr();
129: ShowData();
130: }
131:
132:
133:
134: return 0;
135:}
Output
โปรแกรมนี้ใน Function ShowData จะทำการแสดงจำนวนของ
Object ทั้งหมดที่อยู่ใน list ด้วย
เพื่อเป็นการประหยัดเนื่อที่จึงไม่นำ Output มาแสดงให้เห็น
อธิบาย Source code
Function
Count มีไว้เพื่อใช้นับจำนวน Object ที่อยู่ใน
list อยู่ระหว่างบรรทัดที่ 19 ถึง
บรรทัดที่ 31
มีการทำงานคือ
ในบรรทัดที่ 24 ถึง บรรทัดที่ 29 จะทำการวน loop เพื่อนับจำนวน Object โดยใช้ตัวแปร i
โดยที่ในแต่ละรอบเราจะให้
Poi ชี้ไปที่ Poi->StNext ไปเรื่อยๆจนกว่า
Poi->StNext จะเท่ากับ Null ก็ให้ ออกจาก loop
ถึงตอนนั้นตัวแปร i จะมีค่าเท่ากับ จำนวน Object
การ Delete Object
เราสามารถใช้ Linked list ในการที่ จะ Insert
Object เราก็จะสามารถ Delete Object ได้ด้วยโดยอัลกอริทึ่มของการ
Delete Object มีดังนี้
การ Delete Object
1.ให้ทำการหา Object ที่ต้องการ Delete ในที่นี้เรียกว่า Delete
2.ให้ทำการหา Object ที่ชี้อยู่ที่ตำแหน่งที่ต้องการ Delete
ในที่นี้เรียกว่า before
3.กำหนด before ชี้ไปที่ ตำแหน่งที่ Delete ชี้อยู่
4.Delete
Object ที่ต้องการ (ไม่ได้แสดงในภาพ)
ดูได้จากรูปที่
14-5
รูปที่ 14-5 แสดงรูปแบบการ Delete ข้อมูล
เราไม่สามารถ Delete Object ที่ไม่ได้สร้างบน free
store ได้ โปรแกรมนี้จึงจะมีการทำงาน ให้ สร้าง Object จากFunction Insert Object เท่านั้น
โปรแกรมที่ 14-6 ตัวอย่างการ
Delete Object
Source code
1:#include"iostream.h"
2:#include"conio.h"
3:#include"string.h"
4:#include"iomanip.h"
5:class Student
6:{
7: private:
8: int
Age;
9: int
Score;
10: char
Name[30];
11: public:
12: int
GetAge(){return Age;}
13: void
SetAge(int Num1){ Age = Num1;}
14: char
*GetName(){return Name;}
15: void
SetName(char Na[])
16: {
17: strcpy(Name,Na);
18: }
19: int
GetScore(){return Score;}
20: void
SetScore(int Num1){Score = Num1;}
21: Student
*StNext;
22:
23:};
24:Student Head;
25:
26:int Count()
27:{
28: Student
*Poi;
29: Poi=
&Head;
30: int i=0;
31: while(1==1)
32: {
33: if(Poi->StNext==0)break;
34: i++;
35: Poi
= Poi->StNext;
36: }
37: return i;
38:}
39:
40:void ShowData()
41:{
42: Student
*Poi;
43: Poi =
&Head;
44: cout
<< "+++++++++++++++++++++++++++++++++++++++++++++++++++++++"
<< endl;
45: cout
<< " Name Age Score" << endl;
46: cout
<< "+++++++++++++++++++++++++++++++++++++++++++++++++++++++"
<< endl;
47: if(Count()
> 0)
48: {
49:
50: while(1==1)
51: {
52: if (Poi->StNext==0)break;
53: Poi
= Poi->StNext;
54:
55: cout
<< setw(20) << Poi->GetName();
56: cout
<< setw(10) << Poi->GetAge();
57: cout
<< setw(8) << Poi->GetScore();
58: cout
<< endl;
59: }
60: }
61: else
62: cout
<< " No data "
<< endl << endl;
63: cout
<< "+++++++++++++++++++++++++++++++++++++++++++++++++++++++"
<< endl;
64: cout
<< " Number of Student is
:" << Count();
65:}
66:
67:void InsertData(Student *SInsert,char Name[])
68:{
69:
70: Student
*Poi;
71: Poi =
&Head;
72: if(strcmp(Name,"")
!=0)
73: {
74: while(1==1)
75: {
76:
77: if(strcmp(Poi->StNext->GetName(),Name)==0)break;
78: Poi = Poi->StNext;
79: }
80:
81: SInsert->StNext
= Poi->StNext;
82: Poi->StNext
= SInsert;
83: }
84: else
85: {
86: Poi->StNext
=SInsert;
87: SInsert->StNext
=0;
88: }
89:
90:}
91:
92:void DeleteData(char Name[])
93:{
94:
95: Student
*Poi;
96: Student
*PoiBefore;
97: Poi =
&Head;
98: PoiBefore
= &Head;
99:
100: Poi =
Poi->StNext;
101:
102: while(1==1)
103: {
104: if(strcmp(Poi->GetName(),Name)==0)break;
105: PoiBefore = Poi;
106: Poi
= Poi->StNext;
107: }
108:
109: if(Count()
> 1)
110: PoiBefore->StNext
= Poi->StNext;
111: else
112: PoiBefore->StNext
=0;
113:
114:
115: delete
Poi;
116:}
117:
118:
119:int main()
120:{
121:
122: int choice;
123:
124: int Age;
125: int Score;
126:
127: char
Name[30];
128: char
Namebefore[30];
129:
130: Head.StNext
=0;
131:
132: while(1==1)
133: {
134: Student
*SIn = new Student;
135: cout
<< endl;
136: cout
<< " Menu." << endl;
137: cout
<< " 1.Insert Data "
<< endl;
138: cout
<< " 2.Delete Data "
<< endl;
139: cout
<< " 3.Show Data "
<< endl;
140: cout
<< " 4.Exit " <<
endl;
141: cout
<< "Please choose menu:";
142: cin
>> choice;
143:
144: if
(choice == 4)break;
145: switch(choice)
146: {
147: case
1:
148: cout
<< " Insert Data"
<< endl;
149: cout
<< " Please enter Name:" ;
150: cin
>> Name;
151: cout
<< " Please enter Age:";
152: cin
>> Age;
153: cout
<< " Please enter Score:";
154: cin
>> Score;
155: if(Count() > 0)
156: {
157: cout
<< "Please enter Name before:" ;
158: cin
>> Namebefore;
159: }
160: else
161: strcpy(Namebefore,"");
162:
163: SIn->SetName(Name);
164: SIn->SetAge(Age);
165: SIn->SetScore(Score);
166:
167: InsertData(SIn,Namebefore);
168:
169: clrscr();
170: break;
171:
172: case
2:
173: if(Count()
> 0)
174: {
175: cout
<< " Delete Data"
<< endl;
176: cout
<< "Please enter Name:";
177: cin
>> Name;
178: DeleteData(Name);
179: }
180: else
181: cout
<< "Not have data" << endl;
182:
183: clrscr();
184: break;
185: case
3:
186: clrscr();
187: ShowData();
188:
189: }
190:
191: }
192:
193:
194: return 0;
195:}
Output โปรแกรมนี้มีความสามารถในการลบข้อมูล
นอกจากนั้นแล้วการแสดงผลข้อมูลก็ยังเปลี่ยนไปอีกด้วย แต่เพื่อเป็นการประหยัดเนื้อที่จึงไม่นำ
Output มาแสดงผล
อธิบาย Source code
โปรแกรมนี้ได้มีการใช้ Function DeleteData เพื่อที่จะเอาไว้ลบข้อมูลใน
list โดยที่ถ้าเราจะใช้ Function นี้เราต้องส่งชื่อของคนที่เราต้องการลบไปด้วย
Function
นี้อยู่ระหว่างบรรทัดที่ 92 ถึง บรรทัดที่ 116โดยการทำงานของ Function
คือ เราจะต้องสร้างตัว Poi เพื่อที่จะทำการหาตัวที่ต้องการลบและก็ให้
Poi ชี้ไปที่ตัวนั้น และเรายังต้องสร้าง Poibefore อีกตัวหนึ่งด้วยเพื่อที่จะทำการชี้ไปที่ Object ที่ StNext
จะชี้ไปที่ Object ที่ต้องการลบ
เช่นถ้าเราต้องการลบ Object แรก
ตัว Poi จะชี้ไปที่ Object แรก
ตัว Poibefore จะชี้ไปที่ Head เพราะว่า StNext ของ Head จะชี้ไปที่
Object แรก
Source
code ในส่วนของการหา Object ที่ต้องการลบจะอยู่ในบรรทัดที่
102 ถึง บรรทัดที่ 107 โดยมีหลัการทำงานคือให้วน
loop ไปเรื่อยๆ จนกว่า Poi->GetName() จะเท่ากับ Name ที่รับพารามิเตอร์มาโดยใช้ Function
strcmp ในการเช็คจากนั้นจะมีการเช็คว่าจำนวนทั้งหมดของ Object
มากกว่า 1 หรือเปล่า
ถ้ามากกว่า
ก็ให้ Poibefore->StNext = Poi->StNext;
ถ้าหากเราต้องการลบ Object แรกก็จะเป็นการให้
Head->StNext ไปชี้ที่ Object
ที่ 2
ถ้าไม่มากกว่า ก็หมายความว่ามี Object เดียว
ก็ให้ Poibefore->StNext = 0;
ถ้ามีแค่ Object เดียวก็ให้ Head ไปชี้ที่ Null แทน
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ความเป็นจริงแล้วเราไม่จำเป็นต้องเช็คจำนวนของ Object ก็ได้ว่าเหลือตัวสุดท้ายหรือเปล่า ในกรณีที่เรา ลบ Object สุดท้าย ซึ่ง StNext ของ Object สุดท้ายจะชี้ไปที่ Null อยู่แล้ว เพราะฉะนั้น
Poibefore->StNext = Poi->StNext
ก็จะเท่ากับ
Poibefore->StNext = 0
ในที่นี้เพื่อให้ Source
code ดูง่ายก็เลยเขียนแบบนี้
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
การใช้ Class สร้าง Linked
list
เราสามารถสร้าง class เพื่อที่จะทำหน้าที่บรรจุ
Object ให้มีการทำงานแบบ Linked list ได้
โดยปกติจะนิยมตั้งชื่อ class ประเภทนี้ว่า collection
หรือไม่ก็ตั้งชื่อให้มีตัว s ต่อท้ายชื่อ class
ที่จะถูกบรรจุ เช่น
เรามี class Student แล้วเราต้องการสร้าง class
ที่ทำหน้าที่บรรจุด Student เราอาจจะตั้งชื่อ Students
ก็ได้
โปรแกรมที่ 14-8 ตัวอย่างการสร้าง
class ที่ทำหน้าที่เป็น บรรจุด Object
Source code
1:#include"iostream.h"
2:#include"conio.h"
3:#include"string.h"
4:#include"iomanip.h"
5:class Student
6:{
7: private:
8: int
Age;
9: int
Score;
10: char
Name[30];
11: public:
12: int
GetAge(){return Age;}
13: void
SetAge(int Num1){ Age = Num1;}
14: char
*GetName(){return Name;}
15: void
SetName(char Na[])
16: {
17: strcpy(Name,Na);
18: }
19: int
GetScore(){return Score;}
20: void
SetScore(int Num1){Score = Num1;}
21: Student
*StNext;
22:
23:};
24:
25:
26:class Collection
27:{
28: public:
29: Student
Head;
30: int
Count();
31: void ShowData();
32: void
InsertData(Student *,char []);
33: void
DeleteData(char []);
34:};
35:
36:int Collection::Count()
37:{
38: Student
*Poi;
39: Poi=
&Head;
40: int
i=0;
41: while(1==1)
42: {
43: if(Poi->StNext==0)break;
44: i++;
45: Poi
= Poi->StNext;
46: }
47: return
i;
48:}
49:
50:void Collection::ShowData()
51:{
52: Student
*Poi;
53: Poi =
&Head;
54: cout
<< "+++++++++++++++++++++++++++++++++++++++++++++++++++++++"
<< endl;
55: cout
<< " Name Age Score" << endl;
56: cout
<< "+++++++++++++++++++++++++++++++++++++++++++++++++++++++"
<< endl;
57: if(Count()
> 0)
58: {
59:
60: while(1==1)
61: {
62: if
(Poi->StNext==0)break;
63: Poi
= Poi->StNext;
64:
65: cout
<< setw(20) << Poi->GetName();
66: cout
<< setw(10) << Poi->GetAge();
67: cout
<< setw(8) << Poi->GetScore();
68: cout
<< endl;
69: }
70: }
71: else
72: cout
<< " No data "
<< endl << endl;
73: cout
<< "+++++++++++++++++++++++++++++++++++++++++++++++++++++++"
<< endl;
74: cout
<< " Number of Student is
:" << Count();
75:}
76:
77:void Collection::InsertData(Student *SInsert,char Name[])
78:{
79:
80: Student
*Poi;
81: Poi
= &Head;
82: if(strcmp(Name,"")
!=0)
83: {
84: while(1==1)
85: {
86://
87: if(strcmp(Poi->StNext->GetName(),Name)==0)break;
88: Poi = Poi->StNext;
89: }
90:
91: SInsert->StNext
= Poi->StNext;
92: Poi->StNext
= SInsert;
93: }
94: else
95: {
96: Poi->StNext
=SInsert;
97: SInsert->StNext
=0;
98: }
99:
100:}
101:
102:void Collection::DeleteData(char Name[])
103:{
104:
105: Student
*Poi;
106: Student
*PoiBefore;
107: Poi
= &Head;
108: PoiBefore
= &Head;
109:
110: Poi
= Poi->StNext;
111:
112: while(1==1)
113: {
114: if(strcmp(Poi->GetName(),Name)==0)break;
115: PoiBefore
= Poi;
116: Poi
= Poi->StNext;
117: }
118:
119: if(Count()
> 1)
120: PoiBefore->StNext
= Poi->StNext;
121: else
122: PoiBefore->StNext
=0;
123:
124:
125: delete
Poi;
126:}
127:
128:
129:int main()
130:{
131:
132: int choice;
133:
134: int Age;
135: int Score;
136:
137: char
Name[30];
138: char
Namebefore[30];
139: Collection
Cl;
140:
141: Cl.Head.StNext
=0;
142:
143: while(1==1)
144: {
145: Student
*SIn = new Student;
146: cout
<< endl;
147: cout
<< " Menu." << endl;
148: cout
<< " 1.Insert Data "
<< endl;
149: cout
<< " 2.Delete Data "
<< endl;
150: cout
<< " 3.Show Data "
<< endl;
151: cout
<< " 4.Exit " <<
endl;
152: cout
<< "Please choose menu:";
153: cin
>> choice;
154:
155: if
(choice == 4)break;
156: switch(choice)
157: {
158: case
1:
159: cout
<< " Insert Data"
<< endl;
160: cout
<< " Please enter Name:" ;
161: cin
>> Name;
162: cout
<< " Please enter Age:";
163: cin
>> Age;
164: cout
<< " Please enter Score:";
165: cin
>> Score;
166: if(Cl.Count()
> 0)
167: {
168: cout
<< "Please enter Name before:" ;
169: cin
>> Namebefore;
170: }
171: else
172: strcpy(Namebefore,"");
173:
174: SIn->SetName(Name);
175: SIn->SetAge(Age);
176: SIn->SetScore(Score);
177:
178: Cl.InsertData(SIn,Namebefore);
179:
180: clrscr();
181: break;
182:
183: case
2:
184: if(Cl.Count()
> 0)
185: {
186: cout
<< " Delete Data"
<< endl;
187: cout
<< "Please enter Name:";
188: cin
>> Name;
189: Cl.DeleteData(Name);
190: }
191: else
192: cout
<< "No data" << endl;
193:
194: clrscr();
195: break;
196: case
3:
197: clrscr();
198: Cl.ShowData();
199:
200: }
201:
202: }
203:
204: return 0;
205:}
Output โปรแกรมนี้สามารถทำงานได้เหมือนโปรแกรมที่
14-7 จึงไม่นำ Output มาแสดงให้ดู และก็ยังไม่มีส่วน
อธิบาย Source code ด้วยเพราะว่า Source code จะคล้ายกับโปรแกรมที่ 14-7 เพียงแต่ Function
ต่างๆจะถูกบรรจุใน class Collection
Double Linked list
Linked
list ที่กล่าวมาก่อนหน้านี้เรียกได้ว่าเป็น Single Linked
list นอกจาก Linked list แบบ Single แล้ว เรายังสามารถสร้าง Linked list อีกรูปแบบหนึ่งได้ โดยเราจะเรียกว่า
Double Linked list โดยที่ Double Linked list จะมีการทำงานคล้าย Single Linked list มาก จะแตกต่างกันก็ตรงที่
Object แต่ละตัวนอกจากจะมี Pointer Nextที่สามารถชี้ไปที่ Object ตัวต่อไปแล้วยังมี Pointer
อีกตัวหนึ่งที่จะทำการชี้ไปที่ Object ตัวก่อนหน้านี้ด้วย
โดยปกติแล้วเรานิยมเรียก Pointer ที่ทำหน้าที่แบบนี้ว่า Back
หรือ Previous