ايجاد ساختارهاي داده اي در ويژوال بيسيک - بخش دوم


ليست پيوندي

همانطور که گفته شد ليست پيوندي مجموعه اي از يکسري داده است که اين داده ها از نوع اشيا خودارجاعي هستند . ( هر شي خودارجاعي داراي يک متغير نوع variant براي نگهدار مقدار و يک اشاره گر به شي بعدي است ) . هر عضو ليست پيوندي را يک گره گويند . هر ليست پيوندي از طريق يک اشاره گر به اولين گره قابل دسترسي است . گره هاي بعدي از طريق قسمت لينک موجود در هر گره قابل دسترس هستند . همچنين لينک آخرين گره با Nothing تنظيم مي شود که انتهاي ليست را نشان مي دهد .
مزيت اصلي ليست هاي پيوندي نسبت به آرايه اينست که تعداد عناصر ليست پيوندي قابل تغيير است . بعبارت ديگر ليست هاي پيوندي بصورت ديناميک هستند و طول آنها قابل تغيير است اما سايز آرايه ثابت است . ( البته ويژوال بيسطک از آرايه هاي با سايز متغير نيز پشتيباني مي کند اما اين عمل تغيير سايز اتوماتيک نيست .)
عمل درج در ليست پيوندي ساده است و تنها بايستي دو اشاره گر تغيير يابد .
ليست هاي پيوندي را مي توان به سادگي با قراردادن هر عضو جديد در محل صحيح بصورت sortشده نگهداري کرد .
اعضاي ليست پيوندي در حافظه بصورت پيوسته ذخيره نمي شوند بنابراين نمي توان فوراً به هر عضو ليست دسترسي داشت ( بر خلاف آرايه ) .
براي ايجاد ليست پيوندي در ويژوال بيسيک نياز به سه کلاس است :

1 – کلاس ClistNode : کلاسي است که هر گره از ليست را توصيف مي کند :

private mNodeData as Variant
private mNextNode as ClistNode
public Property Get Data() as Variant
Data=mNodeData
End Property
Public Property Let Dta(ByVal vNewValue as Variant)x
MNodeData=vNewValue
End Property
Public Property Get NextNode() as ClistNode
Set NextNode=mNextNode
End Property
Public Property Let NextNode(Byval vNewValue as Variant)x
Set mNextNode=vNewValue
End Property



2 – کلاس Clist براي توصيف ليست پيوندي .
mFirstNode براي اشاره به اولين ClistNode و mLastNode براي اشاره به آخرين ClistNode در يک شي clist بکار می رود . زمانيکه يک Clsit ايجاد مي شود اين دو متغير با Nothing تنظيم مي شوند . روال Property Get Iterator يک شي ClistIterator برمي گرداند که مي توان از آن براي حرکت در بين اعضاي ليست استفاده کرد .

Private mFirstNode as ClistNode
Private mLastNode as ClistNode
Public Function IsEmpty() as boolean
IsEmpty=IIf(mFirstNode Is Nothing,True,False)x
End function
Public Sub InsertAtFront(insertItem as variant)x
Dim tempNode as ClistNode
If IsEmpty() then
Set mFirstNode=New ClistNode
Set mLastNode=mFirstNode
Else
Set tempNode=mFirstNode
Set mFirstNode=New ClistNode
MFirstNode.NextNode=tempNode
End if
MFirstNode.Data=insertItem
End sub
Public sub InsertAtBack(insertItem as Variant)x
Dim tempNode as ClistNode
If IsEmpty() then
Set mLastNode=New ClistNode
Set mFirstNode=mLastNode
Else
Set tempNode=mLastNode
Set mLastNode=New ClistNode
TempNode.NextNode=mLastNode
End if
MLastNode.Data=insertItem
End sub
Public function RemoveFromFront()x
Dim removeItem as Variant
If IsEmpty() then
Msgbox list is empty
RemoveFromFront=Null
Exit function
End if
RemoveItem=mFirstNode.Data
If mFirstNode Is mLastNode then
Set mFirstNode=Nothing
Set mLastNode=Nothing
Else
Set mFirstNode=mFirstNode.NextNode
End if
RemoveFromFront=removeItem
End function
Public Function RemoveFromBack()x
Dim removeItem as Variant
Dim current as ClistNode
If IsEmpty() then
Msgboc list is empty
RemovefromBack=Null
Exit function
End if
RemoveItem=mLastNode.Data
If mFirstNode Is mLastNode then
Set mFirstNode=nothing
Set mLastNode=Nothing
Else
Set current=mFirstNode
While Not current.NextNode Is mLastNode
Set current=current.NextNode
Wend
Set mLastNode=current
Current.NextNode=nothing
End if
RemoveFromBack=removeItem
End function
Public property Get Iterator() as variant
Dim iter as ClistIterator
Set iter=New ClistIterator
Iter.StartNode=mFirstNode
Set Iterator=iter
End property


عملکرد روال InsertAtFront :
a – فراخواني IsEmpty براي تعيين خالي بودن ليست
b – اگر ليست خالي باشد mFirstNode و mLastNode به New ClsitNode اشاره مي کنند .
c – اگر ليست خالي نباشد گره جديد توسط اشاره دادن tempNode به اولين گره ليست و سپس اشاره دادن mFirstNode به گره New ClsitNode و سپس اشاره دادن mFirstNode.NextNode به tempNode ساخته مي شود .
d – تنظيم mFirstNode.Data با مقدار مورد نظر
عملکرد روال InsertAtBack :
a – فراخواني IsEmpty براي تعيين خالي بودن ليست
b – اگر ليست خالي باشد mFirstNode و mLastNode به New ClsitNode اشاره مي کنند .
c – اگر ليست خالي نباشد گره جديد توسط اشاره دادن tempNode به آخرين گره ليست و سپس اشاره دادن mLastNode به گره New ClsitNode و سپس اشاره دادن tempNode.NextNode به mLastNode ساخته مي شود .
d – تنظيم mLastNode.Data با مقدار مورد نظر
عملکرد روال RemoveFromFront :
a – اگر ليست خالي باشد Null برگشت داده مي شود .
b – اگر ليست خالي نباشد داده mFirstNode به removeItem اختصاص داده مي شود .
c – اگر ليست فقط يک گره داشته باشد mFirstNode و mLastNode با Nothing مقدار دهي مي شوند و گره از ليست حذف مي شود .
d – اگر گره بيش از يک عضو داشته باشد mFirstNode برابر mFirstNode.NextNode مي شود .
e – مقدار removeItem برگشت داده مي شود .
عملکرد روال RemoveFromBack :
a – اگر ليست خالي باشد Null برگشت داده مي شود .
b – اگر ليست خالي نباشد داده mLastNode به removeItem اختصاص داه مي شود .
c – اگر ليست يک گره داشته باشد mFirstNode و mLastNode با Nothing مقدار دهي مي شوند و گره از ليست حذف مي شود .
d – اگر ليست بيش از يک گره داشته باشد متغير current برابر mFirstNode مي شود . سپس با استفاده از current روي گره هاي ليست حرکت مي کنيم تا به گره اي برسيم که به آخرين گره اشاره مي کند . سپس mLastNode را به گره اي که current به آن اشاره مي کند قرار مي دهيم و مقدار current.NextNode را Nothing مي کنيم تا بعنوان آخرين گزه ليست معرفي شود .
e – مقدار removeItem برگشت داده مي شود .

3 – کلاس ClistIterator : اين کلاس براي حرکت روي گره هاي ليست و دستکاري هر گره بکار مي رود . از حرکت کننده ها براي چاپ ليست و يا انجام دادن عملي بر روي هر عضو Clist مي توان استفاده کرد . اين کلاس داراي دو متغير از نوع ClistNode به نامهاي mBookmark و mFirstNode است . متغير mFirstNode به اولين گره در Clist اشاره مي کند و متغير mBookmark موقعيت فعلي حرکت کننده بر روي Clist را نشان مي دهد . روال Property Let StartNode اين دو متغير را مقدار دهي اوليه مي کند . تابع NextItem اگر مقدار mBookmark برابر Null باشد ، Null برگشت مي دهد و در غيراينصورت مقدار tempData را برابر mBookmark.Data و مقدار mBookmark را برابر mBookmark.NextNode قرار مي دهد . تابع HasMoreItems اگر ليست داراي چندين عضو باشد True برمي گرداند . روال ResetBookmark حرکت کننده را به ابتداي ليست منتقل مي کند .

Private mBookmark as ClistNode
Private mFirstNode as ClistNode
Public Property Let StartNode(Byval vNewValue as variant)x
Set mFirstNode=vNewValue
Set mBookmark=mFirstNode
End property
Public function NextItem()x
Dim tempData as varaint
If mBookmark Is nothing then
NextItem=Null
Else
TempData=mBookmark.Data
Set mBookmark=mBookmark.NextNode
NextItem=tempData
End if
End function
Public function HasMoreItems() as boolean
HasMoreItems=IIf(Not mBookmark Is nothing,True,False)x
End function
Public sub ResetmBookmark()x
MBookmark=mFirstNode
End sub

__________________