Professional Documents
Culture Documents
LINKED LISTS
تعريف .١
تمثيل ألقوائم ألمتصلة .٢
إنشاء قائمة متصلة مفردة .٣
إدخال ألبيانات .٤
التجول في قائمة متصلة مفردة .٥
ألعمليات أالساسية على ألقائمة ألمتصلة ألمفردة .٦
ألبرنامج ألعام .٧
ألقا ئمة ألمتصلة ألمفردة ألدورانية .٨
ألعمليات أالساسية على ألقائمة ألمتصلة ألدورانية .٩
ألبرنامج ألعام .١٠
ألقا ئمة ألمتصلة ألمزدوجة .١١
إنشاء قائمة متصلة مزدوجة .١٢
إدخال ألبيانات .١٣
ألتجول في قائمة متصلة مزدوجة .١٤
ألعمليات أالساسية على ألقائمة ألمتصلة ألمزدوجة .١٥
ألبرنامج ألعام .١٦
ألقا ئمة ألمتصلة ألمزدوجة ألدورانية .١٧
إدخال ألبيانات .١٨
ألتجول في قائمة متصلة مزدوجة دورانية .١٩
تمارين .٢٠
Definition .١تعريف
ألقوائم ألمتصلة ھي تركيب من ألبيانات كل عنصر ) (itemفيھا يسمى عقدة ) .(nodeكل عقدة
تحتوي على حقلين إثنين :
link
ألمؤشر ألذي يؤش:ر عل:ى ألعق:دة أالول:ى يخ:زن ف:ي موق:ع منفص:ل ،يس:مى أل:رأس ) ، (headف:ي
حين ألعقدة أالخي:رة ،تس:مى أالخي:ر ) (lastتؤش:ر عل:ى ف:راغ ) .(NULLألش:كل ٢ -١يوض:ح
ذلك:
head last
Data1 Data2
ألتمثيل ألساكن يمكن إعتباره مصفوفتين إثنين :أالولى للبيانات وأالخرى لالتصال .ھذا ما
نالحظه في ألشكل ٣ -١وكما يلي :
ألبيانات
أالتصال
إن ھذا ألتمثيل ھو عبارة عن صفين متوازيين لھما نفس ألحجم ) (sizeلتخزين كامل للقوائم
ألمتصلة.
من ألناحية أالخرى ،فأن ألطريقة ألكفؤة في تمثيل ألقوائم ألمتصلة ھي ألطريقة ألدينامكية .ففي
ھذه ألطريقة يتكون بنك ألذاكرة ) مجموعة من ألفراغات ألحرة للذاكرة ( ،وقائد )(program
للذاكرة .خالل إنشاء ألقوائم ألمتصلة ،يخصص موقع لكل عقدة في ألذاكرة ويعمل ألقائد في
ألبحث عن عنوان ) (addressذلك ألموقع.
head last
Data1 Data2 Data3 Data4 Data5
*head *last
مالحظة:
إن كلمة ألرأس ) (headھنا تمثل عنوان ألعقدة االولى في ألذاكرة فھي إذن مؤشر
) (pointerيؤشر على ألعقدة أالولى في ألقائمة ألمتصلة.
وأن ألسھم ) (arrowفي كل عقدة يمثل تأشير للعقدة ألتالية.
إن لكل عقدة في ألقائمة ألمتصلة مكونان ) (componentsرئيسيان وھذا ما ذكرناه عند
تعريف ألقائمة ألمتصلة ) حقل ألبيانات وحقل ألمؤشر ،أنظر ألشكل ( ١ -١وعليه فإن ألخطوة
ألمھمة النشاء ألعقدة برمجيا ھي تعريف تركيب ) (structوتكون صيغته على ألنحو ألتالي:
{ struct nod
; int Data
; nod *link
;}
*head
*cur
*last
وعلى ألترتيب.
ألصيغة ألبرمجية لالعالن عن ألمتغيرات ألثالثة يمكن صياغتھا وعلى ألنحو أالتي:
إن ألفكرة ألرئيسية في إنشاء قائمة متصلة مفردة تكمن في حساب قيم ألمؤشرات ألرأس ،ألتيار
وأالخير .يمكن تنفيذ ذلك وذلك بإستخدام ألمؤثر جديد ) (newوألذي بدوره يوفر موقع تخزين
ديناميكي.
{ struct nod
; int Data
; nod *link
;}
; nod *head, *cur, *last
) ( void create
{
; head = new nod
; cur = head
) for (int i = 1 ; i <= 4 ; i++
{
; cur -> link = new nod
; cur = cur -> link
}
; last = cur
; last -> link = NULL
}
) (main
} ; ) ( { create
في ھذا ألبرنامج تم إنشاء قائمة متصلة مفردة متكونة من خمسة عقد ويمكن توضيح ذلك:
ألعبارة
من أجل إنشاء عقدة ألرأس وألتي يمكن تمثيلھا بألشكل ٥ -١
head
*head
أما ألعبارة
; cur = head
فھي تعمل على نسخ ألعقدة ألرأس إلى ألعقدة ألتيار ،يمكن توضيح ذلك بالشكل ٦ -١
head cur
*head, *cur
أما جملة ألتكرار forفھي تعمل على إنشاء بقية ألعقد حيث أن ألعبارة:
فھي لنقل أالسم تيار ) (curإلى ألعقدة ألتالية وألتي تم إنشاؤھا وكما ھو موضح بألشكل ٧ -١
head cur
*head *cur
بعد سلسلة من ألتكرارات نحصل على ألقائمة ألمتصلة ألمفردة ،كما ھو موضح في ألشكل ٨ -١
head cur
*head *cur
; last = cur
وبما أن ألعقدة أالخيرة تؤشر على فراغ ) (NULLفإن ألجملة ألخاصة بذلك ھي:
; last -> link = NULL
إن ألصيغة ألنھائية للقائمة ألمتصلة ألمفردة تكون كما في ألشكل ٩ -١
head last
*head *last
ألشكل ٩ -١قائمة متصلة مفردة
ھنا نوضح كيفية إدخال ألبيانات لكل عقدة من ألعقد ،لقد تم تخص:يص دال:ة ) (functionلق:راءة
ألبيانات من لوحة ألمفاتيح ثم وضع كل قيمة في ألعقدة ألمناسبة.
ألدالة ستكون على ألنحو أالتي:
) ( void read
{
; " cout<< "Enter the value for the head :
; cin>> head -> Data
; cur = head
)while( cur->link
{
; " cout<< " Enter the values of the items :
; cur = cur -> link
; cin>> cur -> Data
}
}
تضمن ألبرنامج أعاله قراءة ،من لوحة ألمفاتيح ،ألقيمة ألخاصة بألرأس وذلك بإستخدام ألعبارة
وذلك للمرور بكافة ألعقد وتخصيص ألقيمة ألبيانية لتلك ألعقد .سوف ينتھي تأثير ألصيغة
ألتكرارية عندما يتحقق ألشرط:
) (main
{
; ) ( create
; ) ( read
}
ألرإس
أربعة عقد متبقية تشمل كذلك أالخير
١
٩ ،٦ ،٥ ،٢
head last
نعني بألتجول في قائمة متصلة ھو زيارة كل عق:دة م:ن عق:د ألقائم:ة مبت:دئين ب:ألرأس حت:ى ألعق:دة
أالخيرة .ألتركيب ألخاص للدالة يكون على ألنحو أالتي:
) (void write
{
;int l = 0
; cur = head
)while (cur
{
" = ] "<<cout<< "Data of node [ " <<l++
;<<cur->Data<<endl
;cur = cur -> link
}
}
إضافة ألدالة إلى ألبرنامج ألسابق مع إجراء أالضافة ألى ألصيغة ألتنفيذية وكما يلي:
) ( main
{
; ) ( create
; ) ( read
; ) ( clrscr
; ) ( write
}
مالحظة:
تم إستخدام ألدالة clrscrوذلك الزالة ألنص من ألنافذة ووضع ألمؤشر عند ألبداية.
بكل تأكيد سوف نضمن برنامجنا بألملف ألرأسي conio.hألذي يحوي ألدالة . clrscr
يفترض ألجزء أالول م:ن ألدال:ة ع:دم إحت:واء ألقائم:ة ألمتص:لة ألمف:ردة عل:ى أي:ة عق:دة وعلي:ه ف:إن
ألعقدة ألجديدة ستكون ھي ألعقدة ألرأس وھي ألعقدة أالخيرة في نفس ألوقت .في ح:ين إن ل:م تك:ن
ألقائمة ألمتصلة ألمفردة خالية فإننا نستطيع إضافة ألعقدة ألجديدة في ألموقع ألمناسب.
ألشكل ١١ -١يوضح ألعبارتين من أالمر elseوھي:
head last
temp
m
*temp
ألشكل ١١ -١إضافة عقدة جديدة لقائمة متصلة مفردة
فھي تعمل على ربط ألعقدة ألجديدة بألعقدة ألرأس ثم يتم إطالق إسم ألرأس على ألعقدة ألجديدة.
ألشكل ١٢ -١يوضح ذلك
last
head
m
يمكن إضافة ھذه ألدالة ليكون ألجزء ألتنفيذي للبرنامج على ألنحو أالتي:
) (main
; ) ( { create
;) ( read
;) ( clrscr
;) ( write
;"cout<<" Enter the Data for the new first node :
;cin>>m
;)adfirst(m
;) ( clrscr
} ;) ( write
فإذا كانت قيمة ألبيانات للعقدة ألجديدة ھي m = 0فإن مخرجات ألبرنامج تكون على ألنحو
أالتي:
أما عند إضافة عقدة جديدة في نھاية ألقائمة ألمتصلة ألمفردة فيمكن تطبيق ألدالة أالتية:
وكم::ا ذكرن::ا س::ابقا وب::إفتراض ب::أن ألج::زء أالول م::ن ألدال::ة يتعام::ل م::ع قائم::ة متص::لة مف::ردة ال
تحتوي على أية عقدة وعليه فإن ألعقدة ألجديدة ستكون ھي ألعق:دةأالخيرة وھ:ي ألعق:دة أل:رأس ف:ي
نف::س ألوق::ت .ف::ي ح::ين إن ل::م تك::ن ألقائم::ة ألمتص::لة ألمف::ردة خالي::ة فإنن::ا نس::تطيع إض::افة ألعق::دة
ألجديدة.
ألشكل ١٣ -١يوضح ألعبارتين من أالمر elseوھي:
head last
temp
n
*temp
ألشكل ١٣-١إضافة عقدة جديدة لقائمة متصلة مفردة
head
last
n
يمكن إضافة ھذه ألدالة ليكون ألجزء ألتنفيذي للبرنامج على ألنحو أالتي:
) (main
; ) ( { create
;) ( read
;) ( clrscr
;) ( write
;"cout<<" Enter the Data for the new end node :
;cin>>n
;)adend(n
;) ( clrscr
} ;) ( write
فإذا كانت قيمة ألبيانات للعقدة ألجديدة ھي n = 10فإن مخرجات ألبرنامج ستكون على ألنحو
أالتي:
Data of node [ 0 ] = 1
Data of node [ 1 ] = 2
Data of node [ 2 ] = 5
Data of node [ 3 ] = 6
Data of node [ 4 ] = 9
Data of node [ 5 ] = 10
أما عند إضافة عقدة جديدة في مكان ما من ألقائمة ألمتصلة ألمفردة فيمكن تطبيق ألدالة أالتية:
ألدالة أعاله تعمل على تحديد موقع ألعقدة ألجديدة وذلك بمعرفة ألعقدة ألتي قبلھا ptrوألعقدة
ألتي بعدھا ، curويتم تحديد ذلك بإستخدام ألصيغة whileحيث تحدد قيمة ألعقدة ألسابقة
بألعبارة
; ptr = cur
مالحظة:
ألدالة أعاله صحيحة عندما تكون ألبيانات مرتبة ترتيبا تصاعديا.
head last
temp
me
temp
me
يتم تحديد ألعقدة ألسابقة وألالحقة للعقدة ألمضافة وكما ھو في بألشكل آالتي ) ألشكل ( ١٧ -١
temp
me
فھي ضرورية جدا وذلك الجراء عملية ربط ألعقدة ألجديدة ) (tempبألعقدتين ألسابقة )(ptr
وألعقدة أالحقة ).(cur
temp
3
فإذا كانت قيمة ألبيانات للعقدة ألجديدة ھي me = 3فإن مخرجات ألبرنامج تكون على ألنحو
أالتي:
حذف عقدة:
إن عملية حذف عقدة من قائمة متصلة مفردة تشبه عملية إضافة عقدة جديدة إلى قائمة متصلة
مفردة .إن ألحذف سيكون من ألماقع أالتية:
) (void defirst
{
;cur = head
;head = head -> link
;delete cur
}
عند تطبيق ھذه ألدالة لحذف ألعقدة ألرأس من ألقائمة ألمتصلة ألمفردة فإن أولى ألخطوات ھي
تسمية ألعقدة ألرأس بألعقدة تيار ):(cur
; cur = head
أما ألعبارة
;head = head -> link
فتعمل على نقل ألمؤشر headإلى ألعقدة ألتالية وكما ھو موضح بألشكل ٢٠ -١
head last
2 5 6 9
) (void delast
{
; cur = head
) while (cur -> link != last
;cur = cur -> link
;delete last
; last = cur
;last -> link = NULL
}
فألعبارة أالولى
; cur = head
تعمل على تسمية ألعقدة ألرأس بألعقدة ألتيار ) (curوكما في ألشكل ٢١ -١
وللوصول إلى ألعقدة ألتي تسبق ألعقدة أالخيرة نطبق ألصيغة أالتية:
head cur
head last
1 2 5 6
وأخيرا ،نعمل على جعل مؤشر ألعقدة أالخيرة يؤشر على ألفراغ .ألصيغة ألبرمجية ھي:
1 2 5 6
Data of node [ 0 ] = 1
Data of node [ 1 ] = 2
Data of node [ 2 ] = 5
Data of node [ 3 ] = 6
وألعقدةhead لحذف عقدة من أية موقع في ألقائمة ألمتصلة ألمفردة ) بإستثناء ألعقدة أالولى
: ( نستخدم ألدالة أالتيةlast أالخيرة
nod *ptr;
cur = head ;
while (cur -> Data != me)
{
ptr = cur ;
cur = cur -> link ;
}
ptr -> link = cur -> link ;
delete cur ;
}
وكما ذكرنا فإن إستخدام ألدالة ال ينطبق على حذف ألعقدة أالولى أو ألعقدة أالخيرة ولبرمجة ھذا
أالستثناء تم إستخدام ألدالة assertوألموجودة في ألملف ألرأسي ، assert.hوھذه ألدالة ھي
إمتداد لجملة ifحيث تعمل على إنھاء ألبرنامج عندما ال يتحقق ألشرط.
لقد تم إستخدام ألدالة ألستثناء ألعقدتين أالولى وألثانية وكما يلي:
فإذا تم إدخال ألقيمة ١وھي ألبيانات ألموجودة في عقدة ألرأس headأو ألقيمة ٩وھي
ألبيانات ألموجودة في ألعقدة أالخيرة lastفسوف تظھر ألصيغة أالتية:
Assertion failed: head -> Data != me, file filename.CPP, line 5,
أو ألصيغة
Assertion failed: last -> Data != me, file filename.CPP, line 6,
أما إذا كانت ألقيمة غير ذلك فإن ألبرنامج سوف يعمل على أالعالن عن عقدة مؤشرھا ptr1
لتكون ألعقدة ألسابقة للعقدة ألمراد حذفھا
; nod *ptr1
تبدأ عملية ألحذف بأن نجعل مؤشر ألعقدة ptr1يؤشر على ألعقدة ألتي تلي ألعقدة ذات ألمؤشر
،curألجملة ألتالية توضح ذلك:
الحظ كيف فصلت ألعقدة .curيمكن أالن حذفھا وبسھولة وكما يلي:
; delete cur
head last
مالحظة:
لحذف عقدة من أية موقع في ألقائم:ة ألمتص:لة يج:ب أن تحم:ل نف:س قيم:ة ألبيان:ات وألت:ي
تساوي قيمة ألمتغير ،meأي يجب أن تكون ألعقدة ألمراد حذفھا داخل ألقائمة ألمتصلة.
)(void destroy
{
;)If( ! head ) exit(1
; cur = head
)while(cur
{
;head = cur -> link
;delete cur
;cur = head
}
;"cout<<" No linked List exist \n
}
)(void initila
{
} ;head = last = NULL
The General Computer Program .٧ألبرنامج ألعام
ألبرنامج أألتي ھو برنامج عام وشامل لكافة ألعمليات ألتي يمكن تنفيذھا على ألقائمة ألمتصلة
ألمفردة ،حيث يشمل ألبرنامج على ما يلي:
># include<iostream.h
># include<conio.h
># include<stdlib.h
># include<assert.h
{ class nod
public:
; int Data
; nod *link
;}
{ class SLL
public:
} ;SLL(int s){size = s
// Function for inserting data for each node in the Linked List
void read ( )
{
cout<< "Enter the value for the head : " ;
cin>> head -> Data ;
cur = head ;
while( cur->link)
{
cout<< " Enter the value of the item : " ;
cur = cur -> link ;
cin>> cur -> Data ;
}
}
// Function for adding a new node at the beginning of the Linked List
void adfirst(int m)
{
if( !head )
{
head = new nod;
head->Data = m;
last = head;
last -> link = NULL;
}
else
{
nod *temp = new nod;
temp -> Data = m;
temp -> link =head;
head = temp;
}
}
// Function for adding a new node at the end of the Linked List
void adend(int n)
{
if( !head )
{
head = new nod;
head->Data = n;
head -> link = NULL;
last = head;
}
else
{
nod *temp = new nod;
temp -> Data = n;
last -> link = temp;
last = temp;
last -> link = NULL ;
}
}
// Function for adding a new node at any place of the Linked List
void adany (int me)
{
nod *temp, *ptr ;
temp = new nod ;
temp -> Data = me ;
cur = head ;
while (cur -> Data < me )
{
ptr = cur ;
cur = cur -> link ;
}
ptr ->link = temp;
temp -> link = cur ;
}
// Function for deleting a node from the beginning of the Linked List
void defirst( )
{
cur = head;
head = head -> link;
delete cur;
}
// Function for deleting a node from the end of the Linked List
void delast( )
{
cur = head ;
while (cur -> link != last )
cur = cur -> link;
delete last;
last = cur ;
last -> link = NULL;
}
// Function for deleting a node from any place of the Linked List
void deany (int me )
{
assert(head -> Data != me);
assert(last -> Data != me);
nod *ptr;
cur = head ;
while (cur -> Data != me)
{
ptr = cur ;
cur = cur -> link ;
}
ptr -> link = cur -> link ;
delete cur ;
}
// Function for destroying the Linked List
void destroy()
{
cur = head ;
while(cur)
{
private:
int size;
nod *head, *cur, *last ;
};
SLL x(4);
main( )
{ x.create ( ) ;
x.read();
clrscr( ) ;
char ch;
int m;
cout<<" \n SELECT A CHARACTER TO RUN ONE OF THE FOLLOWING: "<<endl;
cout<<" ______________________________________________ \n"<<endl;
cout<<" a: for the initialization of the Linked List"<<endl;
cout<<" b: for adding a new node at the beginning of the Linked List "<<endl;
cout<<" c: for adding a new node at the end of the Linked List "<<endl;
cout<<" d: for adding a new node at any place of the Linked List"<<endl;
cout<<" e: for deleting a node from the beginning of the Linked List"<<endl;
cout<<" f: for deleting a node from the end of the Linked List"<<endl;
cout<<" g: for deleting a node from any place of the Linked List"<<endl;
cout<<" h: for destroying the Linked List"<<endl;
cin>>ch;
switch(ch)
{
case 'a': {clrscr( );
x.initila( ) ;
x.write( );
break;}
default: {clrscr( ) ;
exit(5);
}
}
}
ِ سوف تُنشأ قائمة متصلة مفردة ويُطلب ِمنا إدخال ألبيانات،عند تنفيذ ألبرنامج
لكل ِ◌ ِ◌ عقدة مبتدا
.من ألرأس ثم ألمرور بأل ُعقد ألباقية حتى أألخيرة
:بعد ذلك سوف تظھر لنا ألشاشة ألتالية
( وبخالف ذلك سوف نخرج منh إلىa حيث يتوجب علينا إختيار واحد من ألحروف ) من
.ألبرنامج
وألتيswitch إن كل حرف من ألحروف أعاله يدل على عملية يتم تنفيذھا بإستخدام عبارة
سوف يعمل على تنفيذ كافة ألجمل فيcase ألمطلوبة وبدورھا فإن أالمرcase تتضمن ألحالة
.( وألتي تكون من ضمنھا ألدالة ألرئيسية لتنفيذ ألعمليةblock) داخل ألكتلة
Circular Linked List .٨ألقائمة ألمتصلة ألدورانية
في ألمناقشات ألسابقة الحظنا بأن ألقائمة ألمتصلة ألمفردة يؤشر فيھا مؤشر ألعقدة أالخيرة last
على ألفراغ .NULLأما إذا أشر مؤشر ألعقدة أالخيرة على ألعقدة أالولى فإن ألقائمة ألمتصلة
سوف تسمى ألقائمة ألمتصلة ألدورانية ) .(Circularألشكل ٣٠ -١يوضح ذلك:
head last
{ struct nod
; int Data
; nod *link
;}
; nod *head, *cur, *last
) ( void create_Cir
{
; head = new nod
; cur = head
) for (int i = 1 ; i < 4 ; i++
{
; cur -> link = new nod
; cur = cur -> link
}
; last = cur
; last -> link = head
}
) (main
} ; ) ( { create_Cir
لم يختلف ألبرنامج ألحالي Program Chr1_02.cppعن ألبرنامج أالول Program
Chr1_01.cppسوى جملة واحدة فقط وھي:
حيث تم ربط ألعقدة أالخيرة بألعقدة أالولى ،فأصبحت ألقائمة ألمتصلة دورانية ).(Circular
١
٦ ،٥ ،٢
head last
ألتجول في قائمة متصلة دورانية ھو زيارة كل عقدة من عقد ألقائمة مبتدئين بألرأس حتى ألعقدة
أالخيرة .ألتركيب ألخاص للدالة يكون على ألنحو أالتي:
) (void write_Cir
{
;int l = 0
; cur = head
" = ] "<<cout<< "Data of node [ " <<l++
;<<head->Data<<endl
)while (cur ->link != head
{
;cur = cur -> link
" = ] "<<cout<< "Data of node [ " <<l++
;<<cur->Data<<endl
}
}
حشر عقدة:
لحشر عقدة جديدة في بداية ألقائمة ألمتصلة ألدورانية نستخدم ألدالة أالتية:
وكما ذكرنا سابقا،فإن ألجزء ألجزء أالول من ألدالة ينفذ عند عدم إحتواء ألقائمة ألمتصلة
ألدورانية على أية عقدة وعليه فإن ألعقدة ألجديدة ستكون ھي ألعقدة ألرأس وھي ألعقدة أالخيرة
في نفس ألوقت .في حين إن لم تكن ألقائمة ألمتصلة ألدورانية خالية فإننا نستطيع إضافة ألعقدة
ألجديدة في ألموقع ألمناسب.
ألشكل ٣٢ -١يوضح ألعبارتين من أالمر elseوھي:
head last
temp
m
*temp
ألشكل ٣٢ -١إضافة عقدة جديدة لقائمة متصلة دورانية
فھي تعمل على ربط ألعقدة ألجديدة بألعقدة ألرأس ثم يتم إطالق إسم ألرأس على ألعقدة ألجديدة.
ألشكل ٣٣ - ١يوضح ذلك
last
1 2 5 6
head
m
) (main
{
; ) ( create_Cir
;) ( Read_Cir
;) ( clrscr
;) ( write_Cir
;"cout<<" Enter the Data for the new first node :
;cin>>m
;)Adfirst_Cir(m
;) ( clrscr
;) ( write_Cir
}
فإذا كانت قيمة ألبيانات للعقدة ألجديدة ھي m = 0فإن مخرجات ألبرنامج تكون على ألنحو
أالتي:
head last
أما عند إضافة عقدة جديدة في نھاية ألقائمة ألمتصلة ألدورانية فيمكن تطبيق ألدالة أالتية:
وكم:ا ذكرن:ا س:ابقا وب:إفتراض ب:أن ألج:زء أالول م::ن ألدال:ة يتعام:ل م:ع قائم:ة متص:لة دوراني::ة ال
تحتوي على أية عقدة وعليه فإن ألعقدة ألجديدة ستكون ھي ألعق:دةأالخيرة وھ:ي ألعق:دة أل:رأس ف:ي
نف::س ألوق::ت .ف::ي ح::ين إن ل::م تك::ن ألقائم::ة ألمتص::لة ألدوراني::ة خالي::ة فإنن::ا نس::تطيع إض::افة ألعق::دة
ألجديدة.
head last
temp
n
*temp
ألشكل ٣٥ -١إلضافة عقدة جديدة لقائمة متصلة دورانية
أما ألعبارات:
فھي تعمل على ربط ألعقدة أالخيرة بألعقدة ألجديدة ) (*tempثم يتم إطالق إسم أالخيرعلى ألعقدة
ألجديدة .أما ألعبارة أالخيرة فإنھا تعمل على جعل مؤشر ألعقدة أالخيرة يؤشر على ألعقدة ألرأس.
ألشكل ٣٦ -١يوضح ذلك
head
last
n
يمكن إضافة ھذه ألدالة ليكون ألجزء ألتنفيذي للبرنامج على ألنحو أالتي:
) (main
; ) ( { create_Cir
;) ( Read_Cir
;) ( clrscr
;) ( write_Cir
;"cout<<" Enter the Data for the new end node :
;cin>>n
;)Addend_Cir(n
;) ( clrscr
;) (write_Cir }
فإذا كانت قيمة ألبيانات للعقدة ألجديدة ھي n = 8فإن مخرجات ألبرنامج تكون على ألنحو
أالتي:
head last
الحظ بأن ألدالة شبيھة تماما للدالة adanyوألتي تم إستخدامھا عند ألتعامل مع ألقائمة ألمتصلة
ألمفردة فألدالة أعاله تعمل تحديد موقع ألعقدة ألجديدة وذلك بمعرفة ألعقدة ألتي قبلھا ptrوألعقدة
ألتي بعدھا ، curويتم تحديد ذلك بإستخدام ألصيغة whileحيث تحدد قيمة ألعقدة ألسابقة
بألعبارة
; ptr = cur
مالحظة:
وكما ذكرنا سابقا فإن ألدالة أعاله صحيحة عندما تكون ألبيانات مرتبة ترتيبا تصاعديا.
ألشكل ٣٧ -١يوضح إجراء عملية إضافة ألعقدة ألجديدة:
temp
3
ألشكل ٣٧ -١ألقائمة ألمتصلة ألدورانية ألجديدة
فإذا كانت قيمة ألبيانات للعقدة ألجديدة ھي me = 3فإن مخرجات ألبرنامج تكون على ألنحو
أالتي:
Data of node [ 0 ] = 1
Data of node [ 1 ] = 2
Data of node [ 2 ] = 3
Data of node [ 3 ] = 5
Data of node [ 4 ] = 6
head last
حذف عقدة:
إن عملية حذف عقدة من قائمة متصلة دورانية تشبه عملية حذف عقدة من قائمة متصلة مفردة.
فألحذف سيكون من ألمواقع أالتية:
) (void defirst_Cir
{
;cur = head
;head = head -> link
;delete cur
;last - > link = head
}
عند تطبيق ھذه ألدالة لحذف ألعقدة ألرأس من ألقائمة ألمتصلة ألمفردة فإن أولى ألخطوات ھي
تسمية ألعقدة ألرأس بألعقدة تيار ):(cur
; cur = head
أما ألعبارة
;head = head -> link
فتعمل على نقل ألمؤشر headإلى ألعقدة ألتالية
وألخطوة ما قبل أالخيرة تعمل على حذف ألعقدة cur
;delete cur
وألخطوة أألخيرة ھي ربط أألعقدة أألخيرة بألعقدة ألرأس عندھا سيكون ألشكل ألنھائي للقائمة
ألمتصلة ألدورانية ستكون على ألنحو أالتي:
head last
) (main
; ) ({ create_Cir
;) (read_Cir
;) (defirst_Cir
;) (clrscr
} ;) (write_Cir
) (void delast_Cir
{
; cur = head
) while (cur -> link != last
;cur = cur -> link
;delete last
; last = cur
;last -> link = head
}
فألعبارة أالولى
; cur = head
تعمل على تسمية ألعقدة ألرأس بألعقدة ألتيار ) .(curوللوصول إلى ألعقدة ألتي تسبق ألعقدة
أالخيرة نطبق ألصيغة أالتية:
حيث ستتوقف جملة whileعندما تؤشر ألعقدة curعلى ألعقدة أالخيرة .نستطيع أالن
وبسھولة تنفيذ ألجملة:
;delete last
head cur
وأخيرا ،نعمل على جعل مؤشر ألعقدة أالخيرة يؤشر على ألعقدة ألرأس .ألصيغة ألبرمجية ھي:
head last
لحذف عقدة من أية موقع في ألقائمة ألمتصلة ألمفردة ) بإستثناء ألعقدة أالولى headوألعقدة
أالخيرة ( lastنستخدم ألدالة أالتية:
;nod *ptr
; cur = head
)while (cur -> Data != me
{
; ptr = cur
; cur = cur -> link
}
; ptr -> link = cur -> link
; delete cur
}
وكما ذكرنا فإن إستخدام ألدالة ال ينطبق على حذف ألعقدة أالولى أو ألعقدة أالخيرة ولبرمجة ھذا
أالستثناء تم إستخدام ألدالة assertوألموجودة في ألملف ألرأسي ، assert.hوھذه ألدالة ھي
إمتداد لجملة ifحيث تعمل على إنھاء ألبرنامج عندما ال يتحقق ألشرط.
لقد تم إستخدام ألدالة ألستثناء ألعقدتين أالولى وألثانية وكما يلي:
Assertion failed: head -> Data != me, file filename.CPP, line 5,
أو ألصيغة
Assertion failed: last -> Data != me, file filename.CPP, line 6,
أما إذا كانت ألقيمة غير ذلك فإن ألبرنامج سوف يعمل على أالعالن عن عقدة مؤشرھا ptr1
لتكون ألعقدة ألسابقة للعقدة ألمراد حذفھا
; nod *ptr1
فإذا إفترضنا بأن بيانلت ألعقدة ألمراد حذفھا تساوي ) ٥أي أن ( me = 5فإن ألشكل سيكون
على ألنحو أالتي:
تبدأ عملية ألحذف بأن نجعل مؤشر ألعقدة ptr1يؤشر على ألعقدة ألتي تلي ألعقدة ذات ألمؤشر
،curألجملة ألتالية توضح ذلك:
الحظ كيف فصلت ألعقدة .curيمكن أالن حذفھا وبسھولة وكما يلي:
; delete cur
فتكون ألقائمة ألمتصلة ألجديدة كما في ألشكل ٤٤ -١
head last
مالحظة:
لحذف عقدة من أية موقع في ألقائم:ة ألمتص:لة يج:ب أن تحم:ل نف:س قيم:ة ألبيان:ات وألت:ي
تساوي قيمة ألمتغير ،meأي يجب أن تكون ألعقدة ألمراد حذفھا داخل ألقائمة ألمتصلة.
تدمير ألقائمة ألمتصلة:
يمكن إنشاء دالة تعمل على تدمير ألقائمة ألمتصلة ألدورانية وذلك بح:ذف عق:دة تل:و ألعق:دة
مبتدئين بألعقدة ألرأس وحتى ألعقدة أالخيرة:
)(void destroy_Cir
{
;)if(! head ) exit(1
; cur = head
)while(cur -> link != head
{
;head = cur -> link
;delete cur
;cur = head
}
;"cout<<" No linked List exist \n
}
)(void initila_Cir
{
} ; head = last = NULL
ألبرنامج أألتي ھو برنامج عام وشامل لكافة ألعمليات ألتي يمكن تنفيذھا على ألقائمة ألمتصلة
ألمفردة ،حيث يشمل ألبرنامج على ما يلي:
# include<iostream.h>
# include<conio.h>
# include<stdlib.h>
# include<assert.h>
class nod {
public:
int Data ;
nod *link ;
};
class SLL {
public:
SLL(int s){size = s; }
// Function for inserting data for each node in the Circular Linked List
void read_Cir ( )
{
cout<< "Enter the value for the head : " ;
cin>> head -> Data ;
cur = head ;
while( cur->link != head)
{
cout<< " Enter the value of the item : " ;
cur = cur -> link ;
cin>> cur -> Data ;
}
}
// Function for adding a new node at the beginning of the Circular Linked List
void adfirst_Cir(int m)
{
if( !head )
{
head = new nod;
head->Data = m;
last = head;
last -> link = head;
}
else
{
nod *temp = new nod;
temp -> Data = m;
temp -> link =head;
head = temp;
last -> link = head;
}
}
// Function for adding a new node at the end of the Circular Linked List
void addend_Cir(int n)
{
if( !last )
{
last = new nod;
last->Data = n;
head = last;
last -> link = head;
}
else
{
nod *temp = new nod;
temp -> Data = n;
last -> link = temp;
last = temp;
last -> link = head ;
}
}
// Function for adding a new node at any place of the Circular Linked List
void adany_Cir (int me)
{
nod *temp, *ptr ;
temp = new nod ;
temp -> Data = me ;
cur = head ;
while (cur -> Data < me )
{
ptr = cur ;
cur = cur -> link ;
}
ptr ->link=temp;
temp->link = cur ;
}
// Function for deleting a node from the beginning of the Circular Linked List
void defirst_Cir( )
{
cur = head;
head = head -> link;
delete cur;
last -> link = head;
}
// Function for deleting a node from the end of the Circular Linked List
void delast_Cir( )
{
cur = head ;
while (cur -> link != last )
cur = cur -> link;
delete last;
last = cur ;
last -> link = head;
}
// Function for deleting a node from any place of the Circular Linked List
void deany_Cir (int me )
{
assert(head -> Data != me);
assert(last -> Data != me);
nod *ptr;
cur = head ;
while (cur -> Data != me)
{
ptr = cur ;
cur = cur -> link ;
}
ptr -> link = cur -> link ;
delete cur ;
}
main( )
{ x.create_Cir( ) ;
x.read_Cir();
clrscr( ) ;
char ch;
int m;
cout<<" \n SELECT A CHARACTER TO RUN ONE OF THE FOLLOWING: "<<endl;
cout<<" ______________________________________________ \n"<<endl;
cout<<" a: for the initialization of the Linked List "<<endl;
cout<<" b: for adding a new node at the beginning of the Linked List "<<endl;
cout<<" c: for adding a new node at the end of the Linked List "<<endl;
cout<<" d: for adding a new node at any place of the Linked List"<<endl;
cout<<" e: for deleting a node from the beginning of the Linked List"<<endl;
cout<<" f: for deleting a node from the end of the Linked List"<<endl;
cout<<" g: for deleting a node from any place of the Linked List"<<endl;
cout<<" h: for destroying the Linked List "<<endl;
cin>>ch;
switch(ch)
{
case 'a': {clrscr( );
x.initila_Cir();
x.write_Cir();
break;}
default: {clrscr( ) ;
exit(5);
}
}
}
سوف تنشأ قائمة متصلة دورانية ويُطلب ِمنا إدخال،ومثل ما ذكرنا سابقا فعند تنفيذ ألبرنامج
.ألبيانات لكل عقدة ُمبتدا ِمن ألرأس ثم ألمرور بأل ُعقد ألباقية حتى أألخيرة
:بعد ذلك سوف تظھر لنا ألشاشة ألتالية
SELECT A CHARACTER TO RUN ONE OF THE FOLLOWING:
__________________________________________
حيث يتوجب علينا إختيار واحد من ألحروف ) من aإلى ( hوبخالف ذلك سوف نخرج من
ألبرنامج.
إن كل حرف أعاله يدل على عملية يتم تنفيذھا بإستخدام عبارة switchوألتي تتضمن ألحالة
caseألمطلوبة وبدورھا فإن أالمر caseسوف يعمل على تنفيذ كافة ألجمل في داخل ألكتلة
) (blockوألتي تكون من ضمنھا ألدالة ألرئيسية لتنفيذ ألعملية.
{ struct nod
; int Data
; nod *aft
; nod *bef
;}
لكي نطبق ھذا ألتركيب ،علينا أالعالن عن ألمؤشرات أالتية:
وعلى ألترتيب.
Creating a Double linked List .١٢إنشاء قائمة متصلة مزدوجة
إن ألفكرة ألرئيسية في إنشاء قائمة متصلة مزدوجة تكمن في وجود مؤشرين إثنين ،يطلق على
أالول إسم afterويطلق على ألثاني إسم beforeبإالضافة إلى ألمؤشرات ألرأس ،ألتيار
وأالخير .يمكن تنفيذ ذلك وذلك بإستخدام ألمؤثر جديد ) (newوألذي بدوره يوفر موقع تخزين
ديناميكي.
للقائمة ألمتصلة ألمزدوجة فوائد عديدة منھا:
{struct nod
; int Data
; nod * after
; nod *before
;}
) ( void create_D
{
; head = new nod
; head -> before = NULL
; head -> after = NULL
; cura = head
; curb = head
) for (int i = 1 ; i <= 4 ; i++
{
; cura -> after = new nod
; cura = cura -> after
;cura -> before = curb
; curb = curb -> after
}
; last = cura
; last -> after = NULL }
) (main
} ; ) ( { create_D
في ھذا ألبرنامج تم إنشاء قائمة متصلة مزدوجة مكونة من خمسة عقد ويمكن توضيح ذلك:
ألعبارة
من أجل إنشاء عقدة ألرأس وألتي يمكن تمثيلھا بألشكل ٤٥ -١
head
*head
أما ألعبارات
; head -> before = NULL
; head -> after = NULL
فھي تعمل على جعل ألمؤشر ألسابق وألمؤشر ألالحق للعقدة بألتأشير على ألفراغ
).(NULLوعليه تكون ألعقدة كما في ألشكل ٤٦ – ١
head
before after
أما ألعبارات
; cura = head
; curb = head
فھي تعمل على نسخ ألعقدة ألرأس إلى ألعقدة ألتيار ألالحق وألتيار ألسابق ،يمكن توضيح ذلك
بالشكل . ٤٦ -١
head, cura, curb
أما جملة ألتكرار forفھي تعمل على إنشاء بقية ألعقد حيث أن ألعبارة:
فھي لنقل أالسم تيار ) (curaإلى ألعقدة ألتالية وألتي تم إنشاؤھا وكما ھو موضح بألشكل 47 -١
head cura
*head *cura
أما ألعبارات:
;cura -> before = curb
; curb = curb -> after
فھي تعمل على ربط ألعقدة ألجديدة ) (curaبألعقدة ألسابقة ) (curbثم تسمية ألعقدة ألجديدة
بأالسم ) (curbوكما ھو موضح في ألشكل ٤٨ - ١
head cura
*head *cura
; last = cura
وبما أن ألعقدة أالخيرة تؤشر على فراغ ) (NULLفإن ألجملة ألخاصة بذلك ھي:
إن ألصيغة ألنھائية للقائمة ألمتصلة ألمزدوجة تكون كما في ألشكل ٥٠ -١
head last
*head *last
ألشكل ٥٠ -١قائمة متصلة مفردة
ھنا نوضح كيفية إدخال ألبيانات لكل عقدة من ألعقد ،لقد تم تخصيص دالة لقراءة ألبيانات من
لوحة ألمفاتيح ثم وضع كل قيمة في ألعقدة ألمناسبة.
ألدالة ستكون على ألنحو أالتي:
) ( void read_D
; " { cout<< "Enter the value for the head :
; cin>> head -> Data
; cura = head
)while( cura -> after
{
; " cout<< " Enter the values of the items :
; cura = cura -> after
; cin>> cura -> Data
}
}
تضمن ألبرنامج أعاله قراءة ،من لوحة ألمفاتيح ،ألقيمة ألخاصة بألرأس وذلك بإستخدام ألعبارة
) (main
{
; ) ( Create_D
; ) ( Read_D
}
يطلب منا ألبرنامج إدخال قيم لكل من:
ألرإس
أربعة عقد متبقية تشمل كذلك أالخير
١
٩ ،٦ ،٥ ،٢
head last
نعني بألتجول في قائمة متصلة ھو زيارة كل عقدة من عقد ألقائمة مبتدئين بألرأس حتى ألعقدة
أالخيرة .ألتركيب ألخاص للدالة يكون على ألنحو أالتي:
) (void write_D
{
;int l = 0
; cura = head
)while (cura
{
" = ] "<<cout<< "Data of node [ " <<l++
;<<cura->Data<<endl
;cura = cura -> after
}
}
إضافة ألدالة إلى ألبرنامج ألسابق مع إجراء أالضافة ألى ألصيغة ألتنفيذية وكما يلي:
) ( main
{
; ) (Create_D
; ) (Read_D
; ) ( clrscr
; ) (write_D
}
مالحظة:
تم إستخدام ألدالة clrscrوذلك الزالة ألنص من ألنافذة ووضع ألمؤشر عند ألبداية.
بكل تأكيد سوف نضمن برنامجنا بألملف ألرأسي conio.hألذي يحوي ألدالة . clrscr
وكما ذكرنا سابقا فإن للقائمة ألمتصلة ألمزدوجة سھولة ألتجول في كال أالتجاھين:
-من ألرأس إلى أالخير
-من أالخير إلى ألرأس
إن ألدالة أعاله سھلة عملية ألتجول من ألرأس وحتى أالخير ،أما إذا أردنا ألتجول من أالخير إلى
ألرأس فألدالة أالتية تقدم لنا ھذه ألخدمة:
void write_DR( )
{
cout<<"\n writing the data of the Circular Linked List in reverse order: \n\n";
int l = 4;
curb = last ;
while (curb)
{
cout<< "Data of node [ " <<l--<<" ] = "
<<curb->Data<<endl;
curb = curb -> before;
}
}
Data of node [ ٤ ] = ٩
Data of node [ ٣ ] = ٦
Data of node [ 2 ] = 5
Data of node [ ١ ] = ٢
Data of node [ ٠ ] = ١
:حشر عقدة
:لحشر عقدة جديدة في بداية ألقائمة ألمتصلة ألمزدوجة نستخدم ألدالة أالتية
void adfirst_D(int m)
{
if(!head)
{
head = new nod;
head->Data = m;
head -> after = NULL;
last = head;
;last -> before = NULL
}
else
{
;nod *temp = new nod
;temp -> Data = m
;temp -> after =head
; head -> before = temp
;temp -> before = NULL
;head = temp
}
}
يفترض ألجزء أالول من ألدالة عدم إحتواء ألقائمة ألمتصلة ألمزدوجة على أية عقدة وعليه فإن
ألعقدة ألجديدة ستكون ھي ألعقدة ألرأس وھي ألعقدة أالخيرة في نفس ألوقت .في حين إن لم تكن
ألقائمة ألمتصلة ألمزدوجة خالية فإننا نستطيع إضافة ألعقدة ألجديدة في ألموقع ألمناسب.
ألشكل ٥٢ -١يوضح ألعبارتين من أالمر elseوھي:
head last
temp
m
*temp
ألشكل 52 -١إضافة عقدة جديدة لقائمة متصلة مزدوجة
أما ألعبارات:
فھي تعمل على ربط ألعقدة ألجديدة بألعقدة ألرأس ثم يتم إطالق إسم ألرأس على ألعقدة ألجديدة.
ألشكل 53 -١يوضح ذلك
last
head
m
يمكن إضافة ھذه ألدالة ليكون ألجزء ألتنفيذي للبرنامج على ألنحو أالتي:
) (main
; ) ( { create_D
;) ( Read_D
;) ( clrscr
;) ( write_D
;"cout<<" Enter the Data for the new first node :
;cin>>m
;)Adfirst_D(m
;) ( clrscr
;) ( write_D }
فإذا كانت قيمة ألبيانات للعقدة ألجديدة ھي m = 0فإن مخرجات ألبرنامج تكون على ألنحو
أالتي:
أما عند إضافة عقدة جديدة في نھاية ألقائمة ألمتصلة ألمزدوجة فيمكن تطبيق ألدالة أالتية:
وكما ذكرنا سابقا وبإفتراض بأن ألجزء أالول من ألدالة يتعامل مع قائمة متصلة مزدوجة ال
تحتوي على أية عقدة وعليه فإن ألعقدة ألجديدة ستكون ھي ألعقدةأالخيرة وھي ألعقدة ألرأس في
نفس ألوقت .في حين إن لم تكن ألقائمة ألمتصلة ألمزدوجة خالية فإننا نستطيع إضافة ألعقدة
ألجديدة.
ألشكل 54 -١يوضح ألعبارتين من أالمر elseوھي:
head last
temp
n
*temp
ألشكل 54 -١إضافة عقدة جديدة لقائمة متصلة مزدوجة
أما ألعبارات:
; last -> after = temp
; temp -> before = last
; last = temp
; last -> after = NULL
فھي تعمل على ربط ألعقدة أالخيرة بألعقدة ألجديدة ثم يتم إطالق إسم أالخيرعلى ألعقدة ألجديدة
وألعبارة أالخيرة تجعل من مؤشر ألعقدة أالخيرة يؤشر على ألفراغ.
ألشكل ١٤ -١يوضح ذلك
head
last
n
يمكن إضافة ھذه ألدالة ليكون ألجزء ألتنفيذي للبرنامج على ألنحو أالتي:
) (main
; ) ( { create_D
;) ( read_D
;) ( clrscr
;) ( write_D
;"cout<<" Enter the Data for the new end node :
;cin>>n
;)addend_D(n
;) ( clrscr
;) ( write_D }
فإذا كانت قيمة ألبيانات للعقدة ألجديدة ھي n = 10فإن مخرجات ألبرنامج تكون على ألنحو
أالتي:
Data of node [ 0 ] = 1
Data of node [ 1 ] = 2
Data of node [ 2 ] = 5
Data of node [ 3 ] = 6
Data of node [ 4 ] = 9
Data of node [ 5 ] = 10
أما عند إضافة عقدة جديدة في مكان ما من ألقائمة ألمتصلة ألمزدوجة فيمكن تطبيق ألدالة أالتية:
ألدالة أعاله تعمل على تحديد موقع ألعقدة ألجديدة وذلك بمعرفة ألعقدة ألتي قبلھا ptr1وألعقدة
ألتي بعدھا ، curaويتم تحديد ذلك بإستخدام ألصيغة whileحيث تحدد قيمة ألعقدة ألسابقة
بألعبارة
; ptr1 = cura
ألشكل 56 -١يوضح إنشاء ألعقدة ألجديدة ) (*tempثم إجراء عملية ربط بين أألعقدة ألجديدة
) (tempوألعقدتين ألسابقة وألالحقة لھا وكما يلي:
n
إن عملية حذف عقدة من قائمة متصلة مزدوجة تشبه عملية حذف عقدة من قائمة متصلة مفردة.
إن ألحذف سيكون من ألمواقع أالتية:
) (void defirst_D
{
;cura = head
;head = head -> after
;delete cura
; head -> before = NULL
}
عند تطبيق ھذه ألدالة لحذف ألعقدة ألرأس من ألقائمة ألمتصلة ألمزدوجة فإن أولى ألخطوات ھي
تسمية ألعقدة ألرأس بألعقدة تيار ):(cura
; cura = head
أما ألعبارة
;head = head -> after
فتعمل على نقل ألمؤشر headإلى ألعقدة ألتالية ،وألخطوة ألتالية تعمل على حذف ألعقدة
cura
;delete cura
وأخيرا نعمل على جعل ألمؤشر beforeللعقدة ألرأس يؤشر على ألفراغ
head last
) (main
; ) ({ create_D
;) (read_D
;) (defirst_D
;) (clrscr
;) (write_D }
) (void delast_D
{
; curb = last
; last = last -> before
;delete curb
;last -> after = NULL
}
فألعبارة أالولى
; curb = last
تعمل على تسمية ألعقدة ألرأس بألعقدة ألتيار ) (curbوأما ألعبارة ألثانية فتعمل على تسمية
ألعقدة ألسابقة للعقدة أالخيرة بألعقدة أالخيرة كما في ألشكل ٥٨ -١
head last
لحذف عقدة من أية موقع في ألقائمة ألمتصلة ألمزدوجة ) بإستثناء ألعقدة أالولى head
وألعقدة أالخيرة ( lastنستخدم ألدالة أالتية:
;nod *ptr1
; cura = head
)while (cura -> Data != me
{
; ptr1 = cura
; cura = cura -> after
}
; curb = cura -> after
; ptr1 -> after = curb
; curb -> before = ptr1
; delete cura
}
وكما ذكرنا فإن إستخدام ألدالة ال ينطبق على حذف ألعقدة أالولى أو ألعقدة أالخيرة فلقد تم
إستخدام ألدالة assertألستثناء ألعقدتين أالولى وأالخيرة وكما يلي:
فإذا تم إدخال ألقيمة ١وھي ألبيانات ألموجودة في عقدة ألرأس headأو ألقيمة ٩وھي
ألبيانات ألموجودة في ألعقدة أالخيرة lastفسوف تظھر ألصيغة أالتية:
Assertion failed: head -> Data != me, file filename.CPP, line 5,
أو ألصيغة
Assertion failed: last -> Data != me, file filename.CPP, line 6,
أما إذا كانت ألقيمة غير ذلك فإن ألبرنامج سوف يعمل على أالعالن عن عقدة مؤشرھا ptr1
لتكون ألعقدة ألسابقة للعقدة ألمراد حذفھا ،وأالعالن ھو
; nod *ptr1
فإذا إفترضنا بأن بيانلت ألعقدة ألمراد حذفھا تساوي ) ٥أي أن ( me = 5فإن ألشكل سيكون
على ألنحو أالتي:
head last
مالحظة:
-لحذف عقدة من أية موقع في ألقائمة ألمتصلة يجب أن تحمل نفس قيمة ألبيان:ات
وألتي تساوي قيمة ألمتغير ،meأي يجب أن تكون ألعق:دة ألم:راد ح:ذفھا داخ:ل
ألقائمة ألمتصلة.
-البتداء قائمة متصلة يمك:ن إس:تخدام ألدال:ة ألمعرف:ة بإس:م initilaوألمس:تخدمة
في ألبرنامج ألعام program Chr1-02
-كذلك ألحال بألنسبة للدالة .destroy
The General Computer Program .١٦ألبرنامج ألعام
ألبرنامج أألتي ھو برنامج عام وشامل لكافة ألعمليات ألتي يمكن تنفيذھا على ألقائمة ألمتصلة
ألمزدوجة ،حيث يشمل ألبرنامج على ما يلي:
># include<iostream.h
># include<conio.h
># include<stdlib.h
># include<assert.h
{ class nod
public:
; int Data
; nod *after
; nod *before
;}
{ class SLL
public:
} ;SLL(int s){size = s
// Function for inserting data for each node in the Double Linked List
void read_D ( )
{
cout<< "Enter the value for the head : " ;
cin>> head -> Data ;
cura = head ;
while( cura -> after)
{
cout<< " Enter the values of the items : " ;
cura = cura -> after ;
cin>> cura -> Data ;
}
}
// Function for adding a new node at the beginning of the Double Linked List
void adfirst_D(int m)
{
if(!head)
{
head = new nod;
head->Data = m;
head -> after = NULL;
last = head;
last -> before = NULL;
}
else
{
nod *temp = new nod;
temp -> Data = m;
temp -> after =head;
head -> before = temp ;
temp -> before = NULL;
head = temp;
}
}
// Function for adding a new node at the end of the Double Linked List
void addend_D(int n)
{
if( !last )
{
last = new nod;
last->Data = n;
last -> after = NULL ;
last -> before = NULL ;
head = last ;
}
else
{
nod *temp = new nod ;
temp -> Data = n ;
last -> after = temp ;
temp -> before = last ;
last = temp ;
last -> after = NULL ;
}
}
// Function for adding a new node at any place of the Double Linked List
void adany_D (int me)
{
nod *temp, *ptr1 ;
temp = new nod ;
temp -> Data = me ;
cura = head ;
while (cura -> Data < me )
{
ptr1 = cura ;
cura = cura -> after ;
}
ptr1 -> after=temp;
temp-> after = cura ;
}
// Function for deleting a node from the beginning of the Double Linked List
void defirst_D( )
{
cura = head;
head = head -> after;
delete cura;
head -> before = NULL ;
}
// Function for deleting a node from the end of the Double Linked List
void delast_D( )
{
curb = last ;
last = last -> before ;
delete curb;
last -> after = NULL;
}
// Function for deleting a node from any place of the Double Linked List
void deany_D(int me )
{
assert(head -> Data != me);
assert(last -> Data != me);
nod *ptr1;
cura = head ;
while (cura -> Data != me)
{
ptr1 = cura ;
cura = cura -> after ;
}
curb = cura -> after ;
ptr1 -> after = curb ;
curb -> before = ptr1 ;
delete cura ;
}
private:
int size;
nod *head, *cura, *curb, *last ;
};
SLL x(4);
main( )
{ x.create_D( ) ;
x.read_D();
clrscr( ) ;
char ch;
int m;
cout<<" \n SELECT A CHARACTER TO RUN ONE OF THE FOLLOWING: "<<endl;
cout<<" ______________________________________________ \n"<<endl;
cout<<" a: for the initialization of the Linked List "<<endl;
cout<<" b: for adding a new node at the beginning of the Linked List "<<endl;
cout<<" c: for adding a new node at the end of the Linked List "<<endl;
cout<<" d: for adding a new node at any place of the Linked List"<<endl;
cout<<" e: for deleting a node from the beginning of the Linked List"<<endl;
cout<<" f: for deleting a node from the end of the Linked List"<<endl;
cout<<" g: for deleting a node from any place of the Linked List"<<endl;
cout<<" h: for destroying the Linked List "<<endl;
cin>>ch;
switch(ch)
{
case 'a': {clrscr( );
x.initila_D();
x.write_D();
break;}
default: {clrscr( ) ;
exit(5);
}
}
}
وكما ذكرنا سابقا فعند تنفيذ ألبرنامج ،سوف تُنشأ قائمة متصلة مزدوجة ويُطلب ِمنا إدخال
ألبيانات لكل عقدة ُمبتدا ِمن ألرأس ثم ألمرور بألعُقد ألباقية حتى أألخيرة.
بعدھا سوف تظھر لنا ألشاشة ألتالية:
حيث يتوجب علينا إختيار واحد من ألحروف ) من aإلى ( hوبخالف ذلك سوف نخرج من
ألبرنامج.
في ألمناقشات ألسابقة الحظنا بأن ألقائمة ألمتصلة ألمزدوجة يؤشر فيھا مؤشر ألعقدة أالخيرة
lastعلى ألفراغ .NULLفإذا أشر مؤشر ألعقدة أالخيرة على ألعقدة ألرأس:
فإن ألقائمة ألمتصلة ألمزدوجة سوف تسمى ألقائمة ألمتصلة ألمزدوجة ألدورانية ).(Circular
ألشكل ٦٢ -١يوضح ذلك:
head last
وعليه ،النشاء قائمة متصلة مزدوجة دورانية ناتبع ألخطوات ألبرمجية أالتية:
// Program Chr1_04.cpp
# include<iostream.h>
struct nod {
int Data ;
nod *after ;
nod *before ;
};
nod *head, *cura, *curb,*last ;
const int size = ٣ ;
void create_CD ( )
{
head = new nod ;
head -> before = NULL ;
head -> after = NULL ;
cura = head ;
curb = head ;
for (int i = 1 ; i <= size ; i++ )
{
cura -> after = new nod ;
cura = cura -> after ;
cura -> before = curb;
curb = curb -> after ;
}
last = cura ;
last -> after = head ;
head -> before = last ;
}
main( )
{ create_CD ( ) ; }
Inserting data إدخال ألبيانات.١٨
ھنا نوضح كيفية إدخال ألبيانات لكل عقدة من ألعقد ألمتكونة منھا ألقائمة ألمتصلة ألمزدوجة
:ألدورانية إن ألدالة ستكون على ألنحو أالتي
void read_CD ( )
{ cout<< "Enter the value for the head : " ;
cin>> head -> Data ;
cura = head ;
while( cura -> after)
{
; " cout<< " Enter the values of the items :
; cura = cura -> after
; cin>> cura -> Data
}
}
نالحظ بأن عملية أالدخال لن تختلف على أالطالق مع تلك ألعملية في حالة ألقائمة ألمتصلة
ألمزدوجة
حيث يطلب ِمنا ألبرنامج إدخال قيم لكل من:
ألرإس
ثالثة عقد متبقية تشمل كذلك ألعقدة أالخيرة
١
7 ،٥ ،٢
head last
*head *last
ألشكل ٦٣ -١قائمة متصلة مزدوجة دورانية
حشر عقدة:
لحشر عقدة جديدة في بداية ألقائمة ألمتصلة ألمزدوجة ألدورانية نستخدم ألدالة أالتية:
يفترض ألجزء أالول من ألدالة عدم إحتواء ألقائمة ألمتصلة ألمزدوجة ألدورانية على أية عقدة
وعليه فإن ألعقدة ألجديدة ستكون ھي ألعقدة ألرأس وھي ألعقدة أالخيرة في نفس ألوقت .في حين
إن لم تكن ألقائمة ألمتصلة ألمزدوجة ألدورانية خالية فإننا نستطيع إضافة ألعقدة ألجديدة في
ألموقع ألمناسب.
ألشكل ٦٤ -١يوضح ألعبارتين من أالمر elseوھي:
head last
temp
m
*temp
ألشكل 64 -١إضافة عقدة جديدة لقائمة متصلة مزدوجة
أما ألعبارات:
فھي تعمل على ربط ألعقدة ألجديدة بألعقدة ألرأس ثم يتم إطالق إسم ألرأس على ألعقدة ألجديدة.
أما عند إضافة عقدة جديدة في نھاية ألقائمة ألمتصلة ألمزدوجة فيمكن تطبيق ألدالة أالتية:
وكما ذكرنا سابقا وبإفتراض بأن ألجزء أالول من ألدالة يتعامل مع قائمة متصلة مزدوجة
دورانية ال تحتوي على أية عقدة وعليه فإن ألعقدة ألجديدة ستكون ھي ألعقدةأالخيرة وھي ألعقدة
ألرأس في نفس ألوقت .في حين إن لم تكن ألقائمة ألمتصلة ألمزدوجة ألدورانية خالية فإننا
نستطيع إضافة ألعقدة ألجديدة.
أما عند إضافة عقدة جديدة في مكان ما من ألقائمة ألمتصلة ألمزدوجة ألدورانية فألمسألة لن
تختلف وعلى أالطالق عن إضافة عقدة جديدة في مكان ما من ألقائمة ألمتصلة ألمزدوجة ھذا ما
نالحظه في ألدالة أالتية :
حذف عقدة:
إن عملية حذف عقدة من قائمة متصلة مزدوجة دورانية تشبه عملية حذف عقدة من قائمة متصلة
مزدوجة .إن ألحذف سيكون من ألمواقع أالتية:
) (void defirst_CD
{
;cura = head
;head = head -> after
;delete cura
; head -> before = last
; last -> after = head
}
ولحذف عقدة من نھاية ألقائمة ألمتصلة ألمزدوجة ألدورانية نستخدم ألدالة أالتية:
) (void delast_CD
{
; curb = last
; last = last -> before
;delete curb
; last -> after = head
; head -> before = last
}
لحذف عقدة من أية موقع في ألقائمة ألمتصلة ألمزدوجة ألدورانية ) بإستثناء ألعقدة أالولى
headوألعقدة أالخيرة ( lastفالمسألة لن تختلف عن ألدالة وألتي تم إستخدامھا في ألقائمة
ألمتصلة ألمزدوجة:
;nod *ptr1
; cura = head
)while (cura -> Data != me
{
; ptr1 = cura
; cura = cura -> after
}
; curb = cura -> after
; ptr1 -> after = curb
; curb -> before = ptr1
; delete cura
}
Exercises .٢٠تمارين
• في ألقائمة ألمتصلة ألمزدوجة ألدورانية ،مؤشر ألعقدة أالخيرة يؤشر على ألعقدة:
• ألعبارة head -> cura -> data ; :تعني طباعة ألبيانات في ألعقدة :
• ألعبارة last -> curb -> data ; :تعني طباعة ألبيانات في ألعقدة :
• أألدالة ألتي تعمل على ھدم أألقئمة ألمتصلة ألمزدوجة أألدورانية تسمى:
; node *ptr
) (void pll
{
; ptr = head
)while(ptr
{
; cout<<ptr -> data
; ptr = ptr -> link
}
; cout<< endl
}
س 4أكتب ألدالة ألتي تعمل على حساب عدد ألعقد في قائمة متصلة مزدوجة دورانية.
س 5أكتب ألدالة ألالزمة لحساب موقع ألعقدة ألتي تحمل أكبر قيمة في قائمة متصلة مفردة.
س 6أكتب ألدالة ألالزمة لحساب موقع ألعقدة ألتي تحمل أصغر قيمة في قائمة متصلة مزدوجة.
س 7أكتب ألدالة ألالزمة لتبديل قيم عقدتين متجاورتين في قائمة متصلة مفردة.
س 8أكتب ألدالة ألالزمة لحساب عدد ألعقد ألمحصورة بين ألعقدة ألرأس وألعقدة أالخيرة في
قائمة متصلة مفردة دورانية.
س 9أكتب ألدالة ألالزمة لعكس قيم ألبيانات في عقد لقائمة متصلة مفردة.
س 10إذا كانت ألعقدة xھي إحدى عقد قائمة متصلة مزدوجة ،أكتب ألدالة ألالزمة لتبديل
ھذه ألعقدة مع ألعقدة ألرأس.
س 11إذا كانت ألعقدة yھي إحدى عقد قائمة متصلة مزدوجة دورانية ،أكتب ألدالة ألالزمة
لتبديل ھذه ألعقدة مع ألعقدة أالخيرة.
س 12إذا كانت Aتمثل قائمة متصلة مزدوجة بياناتھا قيم صحيحة ) سالبة وموجبة ( أكتب دالة
تنشئ قائمتين متصلتين أالولى Bمفردة وألثانية Cمفردة دورانية بحيث تضع في ألقائمة
أالولى ألقيم ألسالبة وفي ألثانية ألقيم ألسالبة.
Q1. Given a single linked list with ten nodes, write the required function for each of
the
following:
• Swap between node number 2 and node number 9
• Put the first node after the last node
• Delete the mid node
• Return the data at node number 6
• Destroy the last four nodes
• Return the number of the nodes