تراكيب البيانات: الحلقات المتسلسلة ثنائية الاتجاه

السلام عليكم

كنا تحدثنا سابقاً عن أنواع الحلقات المتسلسلة
هل تذكرونا بها من فضلكم؟
تفضل يا عبده
الحلقات المتسلسلة أحادية الاتجاه
الحلقات المتسلسلة ثنائية الاتجاه
لولا أني رأيتك وأنت تفتح الدفتر
لقلت أنك أصبحت مجتهداً
سأتغاضى عن ذلك
على أمل أن تدرس جيداً في المرة القادمة

تحدثنا سابقاً عن الحلقات أحادية الاتجاه
وفصلنا فيها بشكل جيد
و الآن جاء الدور على الحلقات ثنائية الاتجاه
و هذا النوع من السلاسل
تتميز روابطه link بأنها في اتجاهين
بمعنى أن الطريق الذي تذهب منه يمكنك الرجعة منه
نمثل الرابطة في هذا النوع بهذا الشكل <–>

نأخذ مثالاً على ذلك محرر الكتابة
المؤشر الذي يتحرك عندما تكتب
يتحرك يميناً وشمالاً
وتستطيع من خلاله أن تضيف حرفاً
إلى القطعة ربما تحذف حرفاً من أمام المؤشر
أو تحذف حرفاً من خلف المؤشر
مثال:
بداية القطعة <–> الحرف الأول <–> الحرف الثاني <–> الحرف الثالث <–> نهاية القطعة

في البرمجة تكون السلسلة كالتالي

بداية السلسلة <–> عقدة رقم 1 <–> عقدة رقم 2 <–> … <–> عقدة رقم ن <–> نهاية السلسلة
مقارنة بسيطة بين الحلقات أحادية وثنائية الاتجاه
الحلقات أحادية الاتجاه أقل في استهلاك الذاكرة
فهي لا تحتوي إلى على روابط في اتجاه واحد
الحلقات ثنائية الاتجاه أسهل في عمليات الحذف والإضافة (من البداية والنهاية)
الحلقات ثنائية الاتجاه أسرع في الاستجابة للأوامر

نجد أن لكلتاهما مزايا وعيوب
بالطبع نقدم إحداهما على الأخرى
على حسب نوعية المشكلة التي تواجهنا

بناء الحلقات ثنائية الاتجاه
نبدأ ببناء الحلقة
الحلقة يجب أن تحتوي على
1- الحلقة التي تسبقها
2- الحلقة التي تليها
3- الكائن الذي تمثله الحلقة
4- صانع كائنات أو أكثر
5- أي إضافات أخرى مثل الدوال خذ وهات set & get methods

أنا قمت بناء واحدة خاصة بي

package DoublyLinkedList;
/**
* @author Alaa AL-Salhi
* @version 1.0
*/
public class DNode {
private DNode next;
private DNode previous;
private Object element;
public DNode() {
this(null,null,null);
}
public DNode(Object element) {
this.next=null;
this.element=element;
}

public DNode(Object element, DNode previous, DNode next) {
this.next=next;
this.element=element;
this.previous=previous;
}

public void setNext(DNode next){
this.next=next;
}
public void setPrevious(DNode previous) {
this.previous = previous;
}
public void setElement(Object o){
this.element=o;
}
public Object getElement(){
return element;
}
public DNode getNext(){
return next;
}
public DNode getPrevious() {
return previous;
}

}

بعد أن قمنا ببناء الفئة حلقة ننتقل إلى الفئة التي ستقوم بإدارة العمليات على السلسلة
هذه الفئة تحتاج إلى التالي
1- أول وآخر عنصر في السلسلة(نحن نعرف أنهما مفيدتان لنا)
2- صانع كائنات
3- دوال الإضافة والحذف
أنا قمت ببناء الفئة DoublyLinkedList الخاصة بي

package DoublyLinkedList;

/**
* @author Alaa AL-Salhi
* @version 1.0
*/

public class DoublyLinkedList {
private DNode tail;
private DNode head;
public DoublyLinkedList(){
head=null;
tail=head;
}
public DoublyLinkedList(Object element){
head=new DNode(element,null,null);
tail=head;
}
public Object getFirst(){
if(head!=null)
return head.getElement();
else
return null;
}
public Object getLast(){
if(tail!=null)
return tail.getElement();
else
return null;
}

public void addFirst(Object element){
DNode newNode;
if(head==null){//set tail at first
newNode=new DNode(element,null,null);
head=tail=newNode;
}
else{
newNode=new DNode(element,null,head);
head=newNode;
}
}

public void addNodeFirst(DNode newNode) {
if(head==null){//set tail at first
head=tail=newNode;
}
else{
DNode temp=head;
head=newNode;
newNode.setNext(temp);
temp.setPrevious(head);
}

}

public Object deleteFirst(){
Object temp=head.getElement();
head=head.getNext();
head.setPrevious(null);
return temp;
}

public void addLast(Object element){
DNode newNode=new DNode(element,null,null);
if(head==null){
head=tail=newNode;
}
else{
tail.setNext(newNode);
newNode.setPrevious(tail);
tail=newNode;
}
}

public void addNodeLast(DNode newNode){
if(head==null){
head=tail=newNode;
}
else{
tail.setNext(newNode);
newNode.setPrevious(tail);
tail=newNode;
}
}

public Object deleteLast(){
DNode temp=head;
if(tail==head){
if(head==null)
return null;
head=tail=null;
return temp.getElement();
}
while(temp.getNext()!=tail)
temp=temp.getNext();
Object objtemp=tail.getElement();
tail.setPrevious(null);//to garbage it
tail=temp;
tail.setNext(null);//to help garbage collector
return objtemp;
}

public void deleteAll(){
while(head!=null)
deleteLast();
}

public static void main(String args[]){
printName("Alaa");
}
public static void printName(String name){
char[] nameCharacters=name.toCharArray();
DoublyLinkedList list=new DoublyLinkedList();
list.addCharacterArrayToList(nameCharacters);
list.print();
list.deleteAll();
list.addRevirselyCharacterArrayToList(nameCharacters);
list.print();

}
public void print() {
if(head==null)
return;
DNode temp=head;
while(temp!=null){
System.out.print(temp.getElement());
temp=temp.getNext();
}
}

public void addRevirselyCharacterArrayToList(char[] characterArray) {
for(int i=characterArray.length-1;i>=0;i--)
addLast(new Character(characterArray[i]));
}

public void addCharacterArrayToList(char[] characterArray) {
for(int i=0;i<characterArray.length;i++)
addLast(new Character(characterArray[i]));
}
public boolean isEmpty(){
return head==null;
}

}

أظن أن الشيفرة التي نراها مألوفة لنا بعض الشيء
على العموم لن أطيل عليكم
كل ما هنالك أني عدلت على الشيفرة الخاصة بـ SinglyLinkedList
هناك احتمالية لوجود أخطاء كالعادة أي خطأ في الشيفرة يرجى تنبيهي

هناك موضوع أريد استشارتكم فيه
كنت أفكر في تغيير التعريب الخاص بـ Linked List من الحلقات المتسلسلة إلى السلاسل
أي الجملتين تجدوهما أقرب إليكم
هل أقوم بالتعديل؟
أم هناك آراء أخرى
كل ما هنالك أني أريد التسهيل عليكم
انتظر آراؤكم بخصوص هذا الشأن

تحياتي

Tags: , , , , , , , , , ,

2 تعليقان to “تراكيب البيانات: الحلقات المتسلسلة ثنائية الاتجاه”

  1. يقول توفيق:

    ارى ان الحلقات المتسلسلة اسرع في الفهم واقرب للذهن
    مجرد راي ليس الا

  2. يقول admin:

    هناك أستاذ لي قال لي في يوم من الأيام
    لا يوجد حل سيء وحل جيد
    يوجد للمشكلة ألف حل لكن أيهم أفضل حل
    لذا تعلم جميع الحلول وافهمها
    حتى إذا وقعت في مشكلة اخترت أفضل الحلول وأقلها تكلفة

    على كل أنا جاهز لأي استفسار حول الموضوع

    تحياتي

Leave a Reply