إعـــــــلان

تقليص
لا يوجد إعلان حتى الآن.

ال Data Structures

تقليص
X
 
  • تصفية - فلترة
  • الوقت
  • عرض
إلغاء تحديد الكل
مشاركات جديدة

  • ال Data Structures

    السلام عليكم ورحمة الله وبركاته ،،
    كيف حال الشباب ،، ان شاء الله طيبيييييييين
    ومبارك عليكم الموقع ،، وان شاء الله سنتواجد عندكم

    بعد غياب طويل عن المنتدى نعود اليكم اليوم مع دورة في ال Data Structures وذلك لاهميتها في البرمجة.

    وسنتناول المواضيع التالية:
    المكدس Stack
    الطابور Queues
    القوائم المرتبطة Linked List
    الاشجار Trees
    والمخططات Graph


    طبعا هذا لن يكون في يوم واحد ،، وانما على عدة ايام ، حتى لا يمل القارئ ، وانا القى وقت للكتابة
    وكذلك سيكون هناك ان شاء الله اسئلة جامدة ،، لذلك شدو الهمم

    وسنستخدم لغة البرمجة C++/C ، اي سنفرق بين كود سي وسي ++ ، وذلك لايضاح الفرق بين اللغتين ، وكذلك لتكون حافز لمبرمجي السي (عاشقي السي ) الى الانتقال الى العالم الاوسع ،،
    عالم ال OOP.

    وقبل ما نبدأ ،، نريد ان نعقد اتفاقية لترجمة المصطلحات ،،
    فالكلمة class لديها مليون معنى بالعربي ،، وهذا شيء غير محبذ على الاطلاق.
    وكذلك الجملة Object Oriented Programming ، والتي قرأت لها عدة ترجمات غريبة !!
    “البرمجة الموجهة نحو الهدف" ، "البرمجة الموجهة جهة الموضوع " ، "البرمجة كائنية المحنى" ، “البرمجة الموجهة للكائنات " و ... الخ.

    وهذا جدول للكلمات اللي راح نستخدمها مع المعاني المنتشرة :

    الكلمة + المعنى
    +++++++++++++++++++++++++++++++++++
    Datat Structure + هياكل البيانات او تراكيب البيانات
    Class + فئة او طبقة او نوع او صنف ،، بصراحة لا أدري ما هو الافضل
    Stack + الرصة او المكدس
    Queue + الطابور او الصف
    ++++++++++++++++++++++++++++++++++

    طبعا مشكلة الترجمة ، قد لا تكون مشكلة كبيرة عند البعض ، ولكنها كارثة بالنسبة لي !!
    تخيل في امتحان لهذه المادة ، كان السؤال الاول
    عرف الاتي: الصف ؟ القائمة المتصلة ؟ الدوال الافتراضية ؟ الصداقة ؟ التحميل الزائد؟
    طبعا اخوكم اخذ يحك رأسه في محاولة لفهم ما هي الترجمة المقابلة !!

    السؤال الثاني :
    لن اضعه ،، حتى لا اتسبب في زيادة كرهي للجامعة " احفظ تنجح ،، افهم ترسب “

    وبسم الله نبدأ ،،

  • #2
    ما هي هياكل البيانات Data Structures:
    هي عبارة عن اوعية "حاويات" للبيانات .
    والمقصود بالوعاء هو مساحة تخرين.

    و اول مثال لهياكل البيانات (والتي لا تحتاج الى تعريف definition ) هي المصفوفات Arrays
    المصفوفة هي عبارة عن حاوية للبيانات ،، حجمها ثابت ،، ويجب ان يكون معلوم في وقت الترجمة .وجميع محتوياتها من نفس النوع . كلام جميل
    اعلان عن مصفوفة A :

    كود:
     int A[5];
    هنا قمنا بحجز مساحة لتخزين 5 اعداد صحيحة ،، ونستطيع استخدامها دون اي مشاكل تذكر.
    طيب هممممممممم ما هي الحاجة الى هياكل "تراكيب" بيانات اخرى ! ما دام ان المصفوفة تعمل ؟!
    الاجابة:
    المصفوفة غير مرنة ،، بمعنى انك لا تستطيع اضافة عنصر اخر وقت تشغيل البرنامج
    وكذلك لا تستطيع حذف عنصر وقت التشغيل ،، اي تجعلها مكونة من 3 اعداد صحيحة فقط
    وكذلك لا تستطيع ان تجعل عدد عناصرها مجهول ، يحدده المستخدم مثلا او تحدده قيمة متغير اخر.
    كل هذه اسباب تجعل المبرمجين يلجؤون الى التفكير بهياكل اخرى.

    اعتقد انك راح تفكر في ان نجعل المصفوفة كبيرة ،، وذلك حتى لا نحتاج الى اضافة "فهي كبيرة بما تكفي" ، وبالنسبة للحذف راح تدبر اي طريقة للتلاعب "لانه لا يمكن حذف اي عنصر من المصفوفة"
    الاجابة:
    المصفوفة الكبيرة تعنى استهلاك كمية من الذاكرة ،، صحيح ان الذاكرة لدي كبيرة ، ولكن هل هي كذلك عند س من الناس ؟
    الامر الاخر وهو الاهم عند الجميع هو سرعة البحث !! ذاكرة كبيرة يعني ان البحث سيكون ابطأ ، ونحن كمبرمجين نريد ان نعطي المستخدم ذاكرة على قدر حاجته .

    امر اخير عن المصفوفات ،، ليس فيها اي نوع حماية ، للاسف
    جرب باستخدام مصفوفتنا الكريمة A ان تدخل اكثر من 5 اعداد ، وشاهد النتجية

    كذلك هناك مشاكل كثيرة problems لايمكن حلها باستخدام المصفوفات العادية ،،
    وراح نتطرق لبعض المشاكل عندما نتقدم قليلا بالدروس.

    اعتقد ان الان وضح سبب الحاجة الى ال Data Structures

    الان راح تقول : تبا للمصفوفات،، وعطنا اللي عندك
    الاجابة : المصفوفات هي الاساس في معظم هياكل البيانات !!

    تااااااااااااااابع

    تعليق


    • #3
      الان وبعد ان تحدثنا قليلا عن المصفوفات وعيوبها ،، جاء دور الانتقال الى اولى هياكل البيانات
      الا وهي المكدس Stack

      ما هو المكدس Stack ؟؟
      هو احد هياكل البيانات ، الاكثر سهولة ، يستخدم بكثرة في عالم الحواسيب : مترجمات ، الات حاسبة ، المعالجات و...الخ.
      ومفهمومها بسيط جدا ،، ادرس المثال الاتي:

      تخيل ان لدينا مجموعة من الاطباق "الصحون" ، مرصوصة فوق بعضها ،اي صحن وفوقه واحد اخر الى ان نصل الى اخر صحن .
      الان لكي نضيف صحن اخر الى المجموعة ، يجب ان نضعه على رأسهم ، يعني اعلى شيء top واذا اردنا ان نسحب اي عنصر ، يجب ان نسحب الذي فوقه اولا .
      اي لا تستطيع سحب الصحن الرابع مثلا دون ان نسحب الصحون التي تقع فوقه ، والا ستنكسر الصحون.

      مثلا اذا اردنا سحب الصحن الثاني ، يجب ان نسحب كل الصحون التي تقع فوقها ، حتى نصل الى الصحن الثاني و نسحبه ،، وتكون المجموعة الجديدة مكونة من الصحن الاول فقط ، وذلك لاننا سحبنا كل الصحون التي تقع فوقها.

      ويتضح المثال بهذا التعريف :
      المكدس هو عبارة عن فكرة "طريقة" تطبق على المصفوفة "ليس في كل الحالات ، ولكن سنستخدم المصفوفة هنا" ،، بحيث ان ادخال العناصر يتم من اعلى "كما في حالة الصحون" ، وكذلك سحب العناصر يتم من اعلى .

      وذلك على خلاف المصفوفة العادية ، مثلا اذا ادخلنا في اي مصفوفة العناصر
      2 ثم 4 ، 6 ، 8 ، 10 .
      واردنا عرضها على الشاشة فان النتيجة هي :
      2 ، 4 ، 6 ، 8 ، 10 اي على نفس ترتيب الادخال .

      ولكن اذا ادخلنا الاعداد السابقة في مكدس ، وعرضنا عناصر المكدس على الشاشة ، فالنتيجة هي:
      10 ، 8 ، 6 ، 4 ،2 اي على عكس ترتيب الادخال .

      اي ان العنصر الداخل الى المكدس اولا ، هو الذي سيخرج في الاخير
      والعنصر الداخل الى اعلى المكدس ، هو الذي سيخرج اولا .
      Last in First Out
      لذلك تجد دائما مع المكدس هذه العباره ، وتختصر ب LIFO

      خلاصة :
      * المكدس هو عبارة عن هيكل بيانات .
      * يتم تطبيق المكدس من خلال المصفوفات او من خلال القوائم المرتبطة "سنتحدث عنها لاحقا"
      * يتبع المكدس مفهوم LIFO ، اي العنصر الذي يدخل في الاخير ، هو الذي يخرج اولا.
      * لادخال عنصرفي المكدس يجب ان نضعه فوق اعلى عنصر .
      كيف سنعرف ان العنصر هو اعلى ام لا ؟

      سنحتاج الى مؤشر للمصفوفة "عدد صحيح " ، وذلك لكي نعرف من هو اعلى عنصر ،، وليكن اسمه top.

      في الحقيقة top ليس مؤشر pointer وانما هو عدد int ، ولكن نستخدمه كدليل الى العنصر الاعلى في المصفوفة ، يعني اذا كان عندي مصفوفة من 10 عناصر ، والمستخدم ادخل قيمة اول عنصرين ، فان المتغير top سيحمل القيمة 1 ، دلالة على ان العنصر الثاني هو اعلى عنصر.

      * عملية ادخال العنصر الى المكدس ، تسمى push ، والتي تعني دفع العنصر الى اعلى المكدس.

      * عملية سحب العنصر من المكدس ، تسمى pop

      صورة توضيحية :



      اعتقد ان المفهوم اتضح قليلا ،، والكود هو خير الكلام ،، ما " قل و دل "
      سنضع كودين ، واحد للغة السي والاخر سي ++ .

      وان كنت افضل كود السي++ وذلك لدعمه "البرمجة كائنية المنحى" هههههههه

      كود مبدئي للمكدس بلغة سي++ :

      كود:
      // Stack using OOD
      #include <iostream>
      #include <stdlib.h>
      
      using namespace std;
      
      class Stack
      {
      private:
      	enum { MAX=10,MIN=-1};  // MAXIMUM,MINIMUM STACK CONTENT
      	int array[MAX]; // Contains all the Data
      	int top;  //Contains location of Top most Data pushed onto Stack
      public:
      	Stack();
      
      	void push(int); // push number to array
      	int pop();    // pop it from array
      
      	bool isEmpty();  // check if array is Empty!
      	bool isFull();	// check if it full
      	
      };
      
      Stack::Stack():
      top(MIN)
      {}
      
      bool Stack::isEmpty()
      {
      	if(top == MIN)
      		return true;
      	else
      		return false;
      }
      
      bool Stack::isFull()
      {
      	if(top == MAX -1)
      		return true;
      	else
      		return false;
      }
      
      void Stack::push(int i)
      {
      	if(isFull())
      	{
      		cout<<"\nArray is Full";
      		exit(1);
      	}
      
      	else
      	{
      		++top;
      		array[top]=i;
      	}
      
      }
      
      
      int Stack::pop()
      {
      	int number;
      
      	if(isEmpty())
      	{
      		cout<<"\nArray is Empty";
      		exit(1);
      	}
      
      	else
      	{
      		number=array[top];
      		top--;
      		
      	}
      	
      	return number;
      
      }
      
      int main()
      {
      	Stack s;
      
      	// push numbers 2,4,8
      	s.push(2);
      	cout<<"\n2 is pushed\n";
      	s.push(4);
      	cout<<"\n4 is pushed\n";
      	s.push(8);
      	cout<<"\n8 is pushed\n";
      
      	// pop numbers
      	cout<<"\n"<<s.pop()<<" is poped"<<endl;
      	cout<<s.pop()<<" is poped"<<endl;
      	cout<<s.pop()<<" is poped"<<endl;
      	return 0;
      }

      كود سي :

      كود:
      // Stack using C Language
      #include <stdio.h>
      #include <stdlib.h>
      
      #define MAX 10
      #define MIN -1
      
      
      struct Stack
      {
      	int array[MAX];
      	int top;
      };
      
      void push(Stack *,int);
      int pop(Stack *);
      void initializeStack(Stack *);
      
      int main()
      {
      	Stack s;
      	initializeStack(&s);
      
      	push(&s,2);
      	printf("\n2 is pushed\n");
      	push(&s,4);
      	printf("\n4 is pushed\n");
      	push(&s,8);
      	printf("\n8 is pushed\n");
      
      	// pop numbers
      	printf("\n %d is pushed\n",pop(&s));
      	printf("\n %d is pushed\n",pop(&s));
      	printf("\n %d is pushed\n",pop(&s));
      	return 0;
      }
      
      
      void initializeStack(Stack *s)
      {
      	(*s).top=MIN;
      }
      void push(Stack *s,int number)
      {
      	if( (*s).top == MAX -1 )
      	{
      		printf("\nArray is Full");
      		exit(1);
      	}
       
      	(*s).top+=1;
      	(*s).array[(*s).top]=number;
      }
      
      int pop(Stack *s)
      {
      	if( (*s).top == MIN )
      	{
      		printf("\nArray is Empty");
      		exit(1);
      	}
      
      	int n=(*s).array[(*s).top];
      	(*s).top--;
      	return n;
      }

      تمت الترجمة ب g++ compiler

      ملاحظات :
      * بقي جزء شرح الكود ، وخاصة المتغير top ، ولكن ان لم تجرب البرامج ، فلن تفهم ما سأقوله ،، لذلك سأنتظر الاسئلة من الاعضاء الذين جربوا البرنامج.
      * هذه البرامج ليست بالشكل النهائي ،اي سنقوم ببعض التعديلات .
      * برنامج السي اعقد قليلا ، وهذا اسهل شيء ، فما بالك ب Trees !!
      * تفضل لغة السي++ في كتابة برامج هياكل البيانات.
      * قم بكتابة هذه البرامج عدة مرات ، حتى يتضح لك المفهوم.

      مميزات وعيوب البرنامج "باللغتين" :
      ميزة واحدة وهي انشاء مكدس.
      نأتي للعيوب:
      المصفوفة ثابتة الحجم !!
      يعني لم نفعل شيء حتى الان !! كل ما فعلناه يمكن ان يتم بمصفوفة بيسطة، شوف المثال:
      كود:
       int array[10];
      for(int i=0;i<10;i++)
       array[i]=i*2+1;
      
      for(int i=9;i>=0;i--)
       cout<<array[i];

      في المثال السابق ادخلنا اعداد فردية على المصفوفة : 1 ، 3 ، ... ، 19
      والنتيجة كانت : 19 ، 17 ، ... ، 1

      هممممممممم ،، وطيب وليش متعبنا مع المكدس وسالفته !!
      الجواب : لاننا سنستخدم برنامج المكدس اللي عملناه ، ونقوم بتطويره .

      طيب ،، ليش ما تعطينا النسخة المطورة وبس ؟؟
      الجواب : اذا ما فهمت الاولى لن تفهم الثانية

      تعبت من الكتاااااااااااااابة ،، انتهت الجلسة
      اي سؤال ؟؟ تعديل ؟؟ اقتراح ؟؟

      ان شاء الله راح تكون في اسئلة جامدة على هياكل البيانات ،،
      الى اللقـــــ مع تحياتي ـــــاء.
      التعديل الأخير تم بواسطة SudaNix; الساعة 10-07-2007, 05:37 PM. سبب آخر: اضافة صورة من wikipedia

      تعليق


      • #4
        بارؤك الله فيك .. تابع ونحن معاك ان شاء الله .. مواضيع ممتازه في الداتا ستراكتشر..
        GCS

        تعليق


        • #5
          باذن الله راح انهي هذه الدورة ،،
          وان شاء الله يستفيد منها الاعضاء.
          وكذلك راح نتحدث عن مواضيع اخرى ، نسيت ان اكتبها :
          Hash Table
          Template
          & other...

          so be close <<
          تحيااااااااااااااااااااااااااتي.

          تعليق


          • #6
            مشكور و جزاك الله كل خير

            اكمل ونحن معك

            تعليق


            • #7
              السلام عليكم
              انت تذاكر من ورانا
              اشتقنالك اخي SudaNix و لمواضيعك القيمة.
              مقال ممتاز الف شكر، واصل ان شاء الله معك.

              تعليق


              • #8
                اهلا بالجميع ،،

                قبل ما نبدأ بتطوير برنامج المكدس السابق ،، احب ان اشرح بعض النقاط
                والتي لم اوضحهها سابقا .

                العمليات على المكدس :
                حتى الان لدينا عملتين two operations وهم :
                1- عملية ادخال العناصر الى المكدس وسميناها push
                2- عملية اخراج العناصر من المكدس وسميناها pop

                العملية push تقوم بادخال العنصر الى المكدس ،، هذا العنصر سيقوم المستخدم بتمريره الى الدالة ()push
                اي اذا اردنا ادخال العنصر 7 مثلا الى المكدس ، كل ما علينا هو استدعاء الدالة وتمرير العنصر 7 اليها كالاتي:

                كود:
                push(7);
                العملية الاخرى وهي pop تقوم بسحب العناصر من المكدس ،، ولتنفيذ هذه العملية يجب ان تستدعي الدالة
                pop() ووضع متغير لكي يحمل قيمة العنصر الذي تم سحبه من المكدس، بهذا الشكل:
                كود:
                int var=pop();
                ++++++++++++++++++++++

                خلينا الحين نتتبع برنامجنا السابق ،،لكي نعرف طريقة عمله ،، وراح اتحدث عن النسخة المكتوبة بلغة سي++
                واذا في احد ما فهم اللي بالسي يقولنا ،،

                على طول ندخل بالدالة الرئسية :

                1
                كود:
                - int main()
                2- {
                3-	Stack s;
                
                4-	// push numbers 2,4,8
                5-	s.push(2);
                6-	cout<<"\n2 is pushed\n";
                7-	s.push(4);
                8-	cout<<"\n4 is pushed\n";
                9-	s.push(8);
                10-	cout<<"\n8 is pushed\n";
                
                11-	// pop numbers
                12-	cout<<"\n"<<s.pop()<<" is poped"<<endl;
                13-	cout<<s.pop()<<" is poped"<<endl;
                14-	cout<<s.pop()<<" is poped"<<endl;
                15-	return 0;
                16- }
                ==============================

                في السطر 3 قمنا بعمل متغير من النوع Stack .
                الان ما الذي سيحدث هنا !!
                طبعا سيتم حجز مساحة للمتغير s وكذلك استدعاء الدالة Stack() بشكل تلقائي ، تعمل هذه الدالة على
                تهيئة المتغير s ، اي اعطائه قيمة ابتدائية ، قبل ان نستخدمه . للمعلومية الدالة stack تسمى بال constructor.
                واذا ذهبنا الى المتغير s في الذاكرة ، راح نشوف انه يتكون من :

                "مصفوفه ثابتة حجمها 10 عناصر وهي array + عدد صحيح وهو top"

                ما يهمنا الان هو القيمة الابتدائية ل top والتي سوف تكون -1 ،، انظر الى ال constructor جيدا .

                +++++++++++++++

                في السطر 5 قمنا باستدعاء الدالة push وتمرير العدد الصحيح 2 ، وذلك حتى ندفعه الى المكدس.
                كيف سيتم ذلك ؟؟

                اولا سوف تقوم الدالة push بعمل اختبار ،، هل المصفوفة ذات ال 10 خانات ممتلئة ام لا ؟؟
                اذا كانت الاجابة نعم ، راح تطلع لك رسالة تنبيه وينتهي البرنامج "طبعا هذا حل غير عملي ، ولكن هذا لغرض التوضيح والتركيز على المشكلة الاساسية "

                واذا كانت الاجابة لا ،، اي ان هناك مساحة خالية لاستقبال عناصر ، فسوف يتم ادخال العدد 2 الى المكدس
                دون مشكلة.

                الاسئلة التي تدور بذهنك حاليا هي:
                كيف نعرف ان المصفوفة ممتلئة او خالية ؟؟
                كيف يتم ادخال العنصر 2 الى المكدس ؟؟

                الفكرة كلها تتمحور حول المتغير top ،، وسوف نطلق عليه الدليل او index .

                كيف يتم ادخال العنصر 2 الى المكدس ؟؟
                الاجابة:
                كما ذكرنا سابقا ،، المكدس يحوي على "مصفوفة من 10 خانات ومتغير top "اطلقنا عليه اسم دليل ذو قيمة ابتدائية -1.
                بالنسبة للمصفوفة فهي تستخدم لتخزين العناصر التي تقوم بتمريرها بواسطة الدالة push

                اما الدليل فهو الذي يخبرنا ان المصفوفة خالية ام لا ؟ وايضا من خلاله نستطيع ادخال العناصر الى المصفوفة اي ان الدليل يعمل ك index للمصفوفة ، وسوف نرى كيف يتم ذلك.

                نرجع الى اجابة السؤال ؟؟ كيف يتم ادخال العنصر 2 الى المكدس ؟؟
                شوف الدالة push
                كود:
                push(int i)
                {
                	if(isFull())
                	{
                		cout<<"\nArray is Full";
                		exit(1);
                	}
                
                	else
                	{
                		++top;
                		array[top]=i;
                	}
                
                }
                اولا تقوم الدلة باجراء اختبار للتأكد من ان المصفوفة ممتلئة ام لا ، لانها لو امتلئت فلا نستطيع ادخال عناصر اخرى،ولنفرض ان المصفوفة خالية.
                بعد ذلك سيتم زيادة المتغير top او الدليل بمقدار واحد "وحط مليون خط على كلمة زيادة"
                اذا ستكون قيمة الدليل هي : -1 + 1 = كم ... اين الالة الحاسبة ، نعم = 0

                وبعدها سيتم ادخال العنصر "وفي مثالنا 2" داخل المصفوفة وبالتحديد داخل array[0]


                +++++++++++++++++++++++

                الاسطر 7 و 9 بنفس الاسلوب السابق ،
                ستكون قمية المتغير top الدليل بعد تنفيذ هذه الاسطر هي 2 ، وذلك لاننا ادخلنا عنصرين الى المكدس.

                اذا سوف تكون لدينا 3 عناصر داخل المصفوفة ، وقيمة الدليل الحالية هي 2.

                ++++++++++++++++++++++++

                اعتقد اننا تجاهلنا هذا السؤال؟ كيف نعرف ان المصفوفة ممتلئة او خالية ؟؟
                الاجابة:
                تكون خالية اذا كانت قيمة الدليل هي -1 "اي لم ندخل اي عدد"
                وتكون ممتلئة اذا كانت قيمة الدليل تساوي "قيمة اكبر عدد من العناصر يمكن ادخاله في المصفوفة ".
                اي اذا كان الدليل يساوي 9 ،، وهو اكبر عدد من العناصر يمكن ادخاله في المصفوفة .

                ++++++++++++++++++++++

                السطر 12و13و14 كلها تعمل بنفس النمط.
                قمنا باستدعاء الدالة pop والتي لديها قيمة معادة ،وهي قيمة العنصرالذي سيتم سحبه من المكدس.

                كيف سيتم ذلك ؟؟ اي كيف سيتم سحب العناصر من المكدس ؟؟
                قبل ان اجاوب على السؤال يجب ان تعرف شيء مهم جدا ،، اعتقد اني تحدثت عنه في احد مواضيع الاخ storm-man
                لا يوجد شيء اسمه حذف قيمة من الذاكرة . يوجد عملية تعيين ، وعملية استعادة
                ولكن حذف فلا يوجد .
                خذ مثال:
                int x;
                cout<<x;

                لما لم تحذف هذه القيمة ؟؟ ما السر في هذا ؟؟
                ببساطة شديدة عندما تحجز مساحة لمتغير وتقوم باعطاء المتغير قيمة :
                int x=1;
                ثم قمت بتحرير الذاكرة ،، مثلا انتهى نطاق المتغير scope ، فان الذاكرة ستكون غير محجوزة ،ولكن عليها قيمة grabage
                وهي 1 ،، وممكن تتغير ،، اذا جاء برنامج اخر وطلب هذه الذاكرة (بدون كتشب) ثم استغنى عنها .

                نرجع الى السؤال ؟كيف سيتم سحب العناصر من المكدس ؟؟
                كما ذكرت سابقا ،، المكدس هو مصفوفة +دليل "سنغير التعريف عندما نتقدم "
                ولكن الان :
                كود:
                while(there is no new lesson)
                {
                	cout<<"المكدس هو مصفوفة + دليل ";
                }
                المصفوفة تستخدم لحفظ العناصر او الاعداد التي يدخلها المستخدم (10 اعداد في مثالنا )
                والدليل يعمل على اخبارنا بان هناك مساحة خالية ام لا ؟ هل المصفوفة ممتلئة ام لا ؟
                وكذلك يعمل ك index في المصفوفة .

                نشوف الدالة pop :
                كود:
                pop()
                {
                	int number;
                
                	if(isEmpty())
                	{
                		cout<<"\nArray is Empty";
                		exit(1);
                	}
                
                	else
                	{
                		number=array[top];
                		top--;
                		
                	}
                	
                	return number;
                
                }
                اولا تختبر هل المصفوفة خالية ام لا ؟ لانها ان كانت خالية ، فماذا سنسحب !!
                وستكون خالية اذا كانت قيمة المتغير top الدليل هي -1 ،، وما عدا هذه القيمة فهي ليست خالية.

                الان نفرض ان المصفوفة تحوي العناصر التي ادخلناها سابقا باستخدام push ، وان top يساوي 2.

                انظر الى هذا الامر جيدا:
                كود:
                number=array[top];
                سيعمل top كدليل في المصفوفة ، اي ستكون هذا الجملة عند اول استدعاء للدالة بهذا الشكل:
                كود:
                number=array[2];
                وبعدها سينقص top بمقدار واحد ، اي سيصبح 1.
                وكهذا تم سحب العنصر من المصفوفة ووضعه في متغير اخر .

                وبنفس الطريقة مع باقي الاستدعاءات.
                ++++++++++++++++++++++

                سؤال للاعضاء :
                كود:
                Stack s;
                s.push(10);
                s.push(20);
                s.pop();
                s.push(30);
                كم عدد العناصر داخل المكدس بعد تنفيذ هذه الجمل ؟ وماهي ؟
                كم قيمة المتغير top ؟
                +++++++++++++++++++++++

                الى هنا انتيهنا من شرح النسخة الاولى لبرنامج المكدس !!
                وسنعمل على تطويرها الان ،، وذلك لانها لاتقبل الا عدد معين من العناصر .
                اتمنى ان اكون قد وفقت في ايصال المعلومة ،،
                اي اخطاء ؟؟ اي سؤال ؟؟

                تابع معنا النسخة المطورة ..

                تعليق


                • #9
                  Stack v0.1


                  Stack v0.1
                  اهلا مجددا ،، :clown:
                  المشكلة الاساسية في النسخة السابقة هو عدد العناصر ثابت .
                  يعني قيمة ثابتة 10 عناصر او 3 او 200 .
                  ومعظم البرامج تستخدم 10 ، ولكن السؤال ؟ هل 10 تكفي لكل انواع واشكال البرامج ؟
                  طبعا لا والف لا .

                  اذا تفضل وخذ نسختك المجانية من المكدس المطور ،، وللعلم انها ايضا لا تطبق بشكل كبير في الواقع !!

                  سوال : انت ذكرت ان النسخة السابقة غير مفيدة بسبب ان عدد العناصر محدود ، وذكرت ان نسختك المطورة هي الحل !!
                  الاجابة :
                  النسخة المطورة هي حل جيد ، فهي تقوم بحل المشكلة الرئسية في النسخة السابقة ، حيث تجعل المستخدم هو الذي سيدخل عدد العناصر، وليس الشخص الذي قام بكتابة ال class .
                  اي اذا اردت ان يكون عدد العناصر 7 فهو كذلك ، 20 ايضا ، 1 ، على كيفك.

                  سؤال : واااااااااو انتهت المشاكل ، ؟ اذا لماذا لا تطبق في الواقع ؟
                  الاجابة : طيب لنفرض يا عزيزي المحترم جاء مستخدم وطلب 20 عنصر ، اوكي.
                  فجأة غير رأيه وقال :20 لاتكفي اريد 30 . هنا المشكلة الاولى .
                  المشكلة الثانية : ان المستخدم من الاول لا يعرف كم يحتاج ، واحد او 10 او 53 .

                  هذه النسخة تتطلب من المستخدم ان يدخل عدد العناصر التي يحتاج اليها ، بدون تغيير الرأي
                  يعني كلمتك تكون كلمة رجال

                  اذا سنحتاج الى نسخة ثالثة واخيرة "ابسط يا عم " تطبق في الواقع بكل المقاييس .
                  ولكن قبل النسخة الاخيرة ، يجب ان ندرس هذه النسخة اولا ،، لانها مفيدة جدا وبسيطة جدا ولكن بشرط "بسيط ايضا ":
                  وهو ان تدخل عدد العناصر التي تحتاج اليها بالضبط.

                  النسخة المطورة : Stack v0.1 :

                  كود:
                  // Stack v0.1 using OOD
                  #include <iostream>
                  #include <stdlib.h>
                  using namespace std;
                  
                  class Stack
                  {
                  private:
                  	enum { MAX=10,MIN=-1};// MAXIMUM,MINIMUM STACK CONTENT	
                  	int *pArray; // pointer to array.
                  	int top;  //Contains location of Top most Data pushed onto Stack
                  	int size; // contain the number of item(integer) you want
                  
                  public:
                  	Stack(int n=MAX);
                  	~Stack();
                  	void push(int); // push number to array
                  	int pop();    // pop it from array
                  	bool isEmpty();  // check if array is Empty!
                  			bool isFull();	// check if it full
                  
                  };
                  
                  Stack::Stack(int n):
                  top(MIN),size(n)
                  {
                  	pArray=new int[n];	
                  }
                  
                  Stack::~Stack()
                  {
                  	delete pArray;
                  	pArray=0;
                  }
                  
                  
                  bool Stack::isEmpty()
                  {
                  	return (top==MIN?ture:false);
                  }
                  
                  bool Stack::isFull()
                  {
                  	return (top==size -1 ?ture:false);
                  }
                  
                  
                  void Stack::push(int i)
                  {
                  	if(isFull())
                  	{
                  		cout<<"\nArray is Full";
                  		exit(1);
                  	}
                  	
                  	else
                  	{	
                  		++top;
                  		*(pArray+top)=i;
                  		// or use this : pArray[top]=i;
                  	}
                  }
                  
                  
                  int Stack::pop()
                  {	
                  	int number;
                  	if(isEmpty())
                  	{
                  		cout<<"\nArray is Empty";
                  		exit(1);
                  	}	
                  	
                  	else
                  	{		
                  		number=pArray[top];
                  		//or use this: number=*(pArray+top);
                  		top--;		
                             }
                  	return number;
                  
                  }
                  
                  
                  int main()
                  {
                  	int number;
                  	cout<<"\nEnter The Number you want\n\t\t>> ";
                  	cin>>number;
                  
                  	Stack s(number);
                  
                  	// push numbers 2,4,8
                  	s.push(2);
                  	cout<<"\n2 is pushed\n";
                  	s.push(4);
                  	cout<<"\n4 is pushed\n";	
                  	s.push(8);
                  	cout<<"\n8 is pushed\n";
                  
                  	// pop numbers
                  	cout<<"\n"<<s.pop()<<" is poped"<<endl;
                  			cout<<s.pop()<<" is poped"<<endl;
                  			cout<<s.pop()<<" is poped"<<endl;
                  	return 0;
                  }
                  فكرة هذه النسخة هي نفس الفكرة السابقة ، اي نفس الدالة push و pop وكذلك نفس الدليل top
                  الاختلاف الوحيد هو في المصفوفة .
                  في المثال السابق كانت مصفوفة ثابتة
                  كود:
                  array[10];
                  اما هنا فاصبحت مؤشر لمصفوفة ديناميكية !!
                  ديناميكية يعني ان حجزها يتم في وقت التنفيذ ،، يعني البرنامج بيشتغل عادي الى ان يصل الى الاعلان:
                  كود:
                  pArray=new int[x];
                  ثم يقوم بحجز المساحة المطلوبة ،، لاحظ في المصفوفة الديناميكية Dynamic Array ان حجمها هو عدد غير ثابت !!يستطيع المستخدم ان يدخله .
                  اذا المصفوفة الدينامييكية dynamic هي السبب في النسخة المطورة

                  طيب ما هو الفرق بين المصفوفة الثابتة static array والمصفوفة الديناميكية dynamic array ؟؟
                  "قبل ما اجاوب ،، احب اذكر عشاق لغة السي الى ان المصفوفة الديناميكية يتم الاعلان عنها باستخدام الدالة malloc والوجودة في الملف الراسي stdlib.h ".

                  الفرق الاول هو ان المصفوفة الثابتة يتم حجزها وقت ترجمة البرنامج ،، اي قبل التشغيل ،، لذلك يجب ان تكون ثابتة الحجم.
                  وبالنسبة للمصفوفة الديناميكية فيتم حجزها وقت التشغيل ،، وبالتحديد عندما يصل البرنامج الى الامر ، مثلا :
                  كود:
                  int x=2;
                  if(x==3)
                  int a=new int;
                  في هذا المثال لن يتم حجز ذاكرة ديناميكية للمتغير a ، مسكين

                  ولكن في هذا المثال:
                  كود:
                  int x=2;
                  if(x==3)
                  int a;
                  سيتم حجز ذاكرة للمتغير a ،، وقت ترجمة البرنامج .

                  الفرق الثاني والاهم ، وهو ان المصفوفة الثابتة يتم حجزها في ذاكرة تسمى stack
                  هذه الذاكرة stack "هي من التطبيقات على موضوعنا ،تعمل بنفس طريقتنا ، لكن لا دخل لنا بها " يتم بها حجز اي متغير ،واي وسيط في دالة ، وكذلك مصفوفتنا الثابتة.
                  وما يميزها هو ان المتغيرات التي بداخلها تحذف بمجرد خروج المتغير من المدى scope تلقائيا ، شوف مثال على الطاير:

                  كود:
                  int main()
                  {
                  	int x=2;
                  
                  	{
                  		int y=4;
                  	}
                  
                  	cout<<x;
                  	cout<<y;
                  	
                  return 0;
                  }
                  هذا البرنامج لن يعمل ،، والسبب هو ان المتغير y قد تم حذفه تلقائيا وذلك لانه خرج من المدى scope

                  اما بالنسبة للمصفوفة الديناميكية (او المتغير الديناميكي )فيتم حجزها على ذاكرة تسمى ب المخزن الحر free store او heap
                  وما يميز هذا ال heap هو ان المتغيرات التي بداخله لا تحذف الا عندما تقوم انت بحذفها ، او عند انتهاء البرنامج .
                  يعني مواضيع ال scope هذه لا تخص الheap
                  شوف المثال :
                  كود:
                  int main()
                  {
                  	int x=2;
                  	int *y;
                  	{
                  		y=new int;
                  		*y=4;
                  	}
                  
                  	cout<<x;
                  	cout<<*y;
                  	delete y;
                  	
                  return 0;
                  }
                  هذا البرنامج سيعمل 100% .
                  تم حجز مساحة ديناميكية للمتغير y ،، واعطائها القيمة 4 .
                  هذه المساحة لن تحذف حتى لو طلعنا من المدى .

                  اغتقد ان بعض الناس راح يسألو ؟؟ ليه ما كتبت داخل ال block الامر :
                  كود:
                  int *y=new int;
                  اي لماذا فصلت الاعلان عن المتغير y وعن حجز الذاكرة ؟؟
                  قبل ما اجاوب اقرأ الملاحظة :

                  "عدم سدادك لفاتورة الهاتف سيؤدي الى .... " اووو معليش ،، اصل التلفون قاطع

                  " عدم حذفك للذاكرة يسبب احد الاخطاء المعروفة ب "تسرب الذاكرة " Memory Leak
                  وهو خطأ قاتل fatal error
                  ولكن في مثالنا البيسط اللى فوق لا يوجد داعي لحذف المتغير y لان البرنامج سوف يتنهي ، ويقوم بحذفه تلقائيا ."


                  طيب لو تجاوبنا مع اخينا السائل ،، وكتبنا البرنامج بهذا الشكل :

                  كود:
                  int main()
                  {
                  	int x=2;
                  
                  	{
                  		int *y=new int;
                  		*y=4;
                  	}
                  
                  	cout<<x;
                  	cout<<*y;
                  	
                  return 0;
                  }
                  الاجابة : يوجد مشكلتين كبيرتين :
                  الاولى :المؤشر y تم حجزه داخل ال block ،، وتم استخدامه خارجها . تذكر انه قد تم حجزه على ال stack
                  المشكلة الثانية : عندما نطلع من ال block مين حيقدر يحرر الذاكرة الديناميكية ، المؤشر y قد مات "اهئ اهئ " بعد الخروج من ال block وهو الوحيد الذي كان يستطيع ان يقوم بحذف الذاكرة .

                  بهذا الشرح الغير مباشر ،، اتمنى ان تكون النسخة المطوره من برنامج المكدس قد وضحت،، واي احد عنده سؤال فلا يتردد ، او يريد شرح مباشر على الهوا ، ايضا لا يتردد.
                  وبالنسبة للنسخة الاخيرة ،، فراح نأجلها كمان جلستين او ثلاث ، وذلك لانها تتعلق بال linked List
                  وهي النسخة المفضلة للجميع ،، وللناس اللى حابه تعرف شكلها ، شوف المثال:
                  كود:
                  int main()
                  {
                  	Stack s;
                  	s.push(2);
                  	s.push(4);
                  		
                  	s.push(8);
                  
                  	...etc
                  
                  	// pop numbers
                  	
                  	return 0;
                  
                  }
                  يعني راح نحل مشكلة ادخال عدد العناصر ،،
                  وكل ماعليك هو ان تدخل الاعداد ، تسحب ، على كيفك .
                  وكمان راح نعمل منها واحدة سوبر "او خليها كمبو هههههههههه"
                  والتي تستخدم حاليا ،، في كل التطبيقات .بحيث تقبل منك اعداد ، حروف ، سلاسل نصية ، قطط ، طائرات ،...الخ.وذلك بواسطة الملكة template

                  الى ذلك الحين ، نستودعكم الله ،، والى اللقاء في حلقة قادمة مع اخو المكدس وهو" ال Queue وبالعربي الطابور وتلفظ كيو".

                  وقبل ما انسى ،، من المفروض حاليا ان اضع الاسئلة "المسخنة" على المكدس ،، ولكني سأنتظر حتى يجهز الجميع.
                  طبعا سنحاول حلها مع بعض اذا لم يتمكن احد من حلها ،، ولكن ان شاء الله الجميع سوف يحلونها .

                  مع السلامة.

                  تعليق


                  • #10
                    المشاركة الأصلية بواسطة fakir مشاهدة المشاركة
                    السلام عليكم
                    انت تذاكر من ورانا
                    اشتقنالك اخي SudaNix و لمواضيعك القيمة.
                    مقال ممتاز الف شكر، واصل ان شاء الله معك.
                    هههههههههههه
                    والله بالاكثر ،، وخليك متابع .
                    تحياتي .
                    +++++++++++++++
                    geo_saleh:
                    العفووو ، وما سوينا الا الواجب :clown:

                    الى اللقاء.

                    تعليق


                    • #11
                      SudaNix

                      بارك الله فيك أخى .


                      just a User innately
                      اللهم اهدنا إلى الطيب من القول ؛ واهدنا إلى صراط الحميد

                      تعليق


                      • #12
                        كم عدد العناصر داخل المكدس بعد تنفيذ هذه الجمل ؟ وماهي ؟
                        ثلاثه ، وهي

                        كود:
                        s.push(10);
                        s.push(20);
                        s.push(30);
                        كم قيمة المتغير top ؟
                        يفترض ثلاثه


                        لأني لم أطبق لكن استفدت كثيراً من الموضوع

                        تعليق


                        • #13
                          مشكور SudaNix ع الموضوع والدرس الجميل .. تم تسيف المووضوع للاستفاده منه لاحقاً .. مع اني اكره البرمجه :angry_red:

                          بالتوفيق

                          Bad3r

                          Twitter
                          : @Linux4SA

                          تعليق


                          • #14
                            كـورس جميل جـدا اخ SudaNix
                            وانا بفضـل انك تعمله كموضوع كلي من غير ردود وتخلي الردود او الاستفسارات اما علي الرسائل الخـاصه او في موضوع منفصـل
                            وشكـرا لـك عزيزي ونحن معـك

                            تعليق


                            • #15
                              تسلم اخوي SudaNix واصل ابداعك
                              تحياتي ،،

                              تعليق

                              يعمل...
                              X