الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

ال Circular Queue

بدأه aimn20 في 1 ديسمبر 2007 · 24 رد · 6,970 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

السلام عليكم ورحة الله ,,,

شباب انا عندي مناقشة عن الكيو والدكتور طلب مني اسوي برنامج لانشاء الكيو وادخال العناصر ( طبعا الكيو يكون دائري)

بس حبيت استفسر هل اسوي الكيو عن طريق الـ array

ولا عن طريق اللينكد ليست

#2

السلام عليكم ,,

حياك الله أخي الكريم ,,

بالنسبة للطوابير الحلقية Circular Queues, فيمكن استخدام Static Array أو Linked Lists لتكون

Low Level Data Structure لها,,

قبل الإجابة على سؤالك ,, يجب معرفة التالي ::

- عدد العناصر هل تريده ثابت Static أم متغير Dynamic.

إذا كان ثابتاُ فبالطبع استخدام مصفوفة ثابتة الحجم Static Array سيكون أسهل بكثير ,, و أكثر كفاءة.

أما إذا كان عدد العناصر متغيراً فاستعمال LInked List هو الخيار الأفضل..

حاول أن تشرح لنا, ما الذي ستستخدمه و سنكون متابعين معك إن شاء الله ,,

إضافة بسيطة,, و هي أن معظم كود Queues على الانترنت,, استخدمت القوالب Templates فيه بدلاُ من تخصيصه لنوع معين كما هو معروف,, و كما هي العادة مع بنى الذاكرة data structure الشائعة ,,

و أيضاُ آذكر أن الـ Circular Buffer سيكون أصعب قليلاُ من الشكل الأصلي أو الـ َ Queue العادي ,,

تحياتي ,,

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 1 ديسمبر 2007 في 23:50

#3

مشكور اخوي على مرورك الكريم

على العموم انا ابي العدد مايكون محدد يعني مفتوح والطريقة بتكون linked listالصراحة انا سويت برنامج عن linked list كيف تسوي عقد وتحذق وتضيف من البدايى والنهاية واشتغل اوكي

بس صراحة الكيو ماعندي فكرة عنه , والمشكلة انه المطلوب مني اسوي circular queue باستخدام اللينكد ليست

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

#4

أعتقد أن المصفوفه أفضل للكيو

إذا استعملت اللينك ليست لن تنتج كيو فعليا إنما سوف تكون تستخدم اللينك ليست بأسلوب شبيه

بإستخدام الكيو

وأعتقد أن بعض التطبيقات التي تستخدم الكيو مثل نظم التشغيل سوف يكون من غير الجيد

استخدام اللينك ليست لها , وذلك بسبب الكفاءة في التنفيذ .

والخيار يعود لك

تحياتي

#5

بس المصفوفة يكون الحجم محدود اما باستخدام الليست يكون الخيار مفتوح لك

وعشان كذا قلت اني سويت برنامج عن الليست

#6

يااخ خلدون

اذا استخدمت مصفوفة راح يكون العدد محدود اما الليست فالخيار متاح لك لادخال اي عدد من العناصر

#7

صحيح أن العدد يكون محدود لكني أعتقد أن استخدام المصفوفه ممكن ان نضطر إليه في بعض

التطبيقات , حيث يكون من الصعب جدا استخدام اللست ,

انا لست ضد اللست , ولكن كطالب برمجه يجب أن يكون لديك فكره قويه عن إستخدامها مع المصفوفات بكفائة .

#8

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

بس المشكلة انه باللست

وعشان كذا انا ادور كود للكيو عن طريق الليست

تم تعديل هذه المشاركة بواسطة aimn20 في 2 ديسمبر 2007 في 23:46

#9

السلام عليكم ,,

يا أخ aimn20 أنا آسف للأخطاء التي ذكرتها في ردي السابق ,,

حيقيقة كانت على عجلة ,,

لأنني بدأت الكلام عن الـ َQueues بشكل عام و أدخلت الـ Circular فيها بالخطأ :hmm:

لكن عليك ,, المفروض استخدام مصفوفة ثابتة الحجم ,, لتصميم Circular Queue أو ما يسمى Data Buffer عادة ,,

لأننا لو فكرنا فليلاُ كما قال الأخ خلدون لا فائدة من Circular Queue و سيتحول إلى Linear إذا صممناه متغير الحجم ,,

لي عودة لشرح الأجزاء الرئيسية في الـ Circular Queue و بعض النقاط التي تسهل من عملية التعامل معه :rolleyes: احتاج فقط للرجوع إلى كتابي المفضل

و أيضاً للأخ خلدون لي عودة للكلام و مناقشة Data Buffers في أنظمة التشغيل و كيفية جعلها Very Optimized للتسريع من عملها بشكل لا يصدق و طبعاُ يتم هذا بالأسمبلي أحياناُ و لكن لنا عودة بعد الفاصل :thumb_up:

#10

السلام عليكم أخ aimn20 ,,

سأبداُ بالشرح و لكن على افتراض أنك تعرف ما هو شكل الـ Circular Queue بالطبع قبل البدء في الكلام حوله ,,

سنحتاج إلى المتغيرات التالية ,,

1 - متغير أو ثابت constant يحمل سعة المصفوفة أو العدد الأقصى للعناص Capacity

2 - مصفوفة من أي نوع ترغب به كـ int على سبيل المثال و يكون حجمها هو Capacity

3 - متغيرين كـ index لمعرفة العنصر الأول في المصفوفة و العنصر الأخير first و last

4 - دالة مساعدة private ,, و ذلك للحصول على رقم العنصر التالي لأي عنصر نختاره ,,

طبعاُ سأذكر لك ما هي فائدة هذه الدالة مع أنه يمكن الاستغناء عنها إلا أننا سنحتاج لكتابة كود الدالة في الكثير من الأمكان أو نقوم باستدعائها و ترك الأمور لها لحساب موقع العنصر التالي لأي عنصر نختاره ,,

طبعاُ كل هذه الأمور سوف تكون في فئة و بالتالي تكون private!

المرة القادمة سوف أشرح ماهي الدالة المساعدة مع شرح بسيط لكيفية حركة البيانات داخل الـ Circular Queue ثم بعد ذلك الكلام عن أشهر الدوال التي تستخدم للتعامل مع الـ Queues كـ pop و push و غيرها,,

تحياتي ,,

#11

السلام عليكم ,,

سنستخدم الدالة المساعدة لحل مشكلة بسيطة في تصميم الـ Circular Queue = CQ نفسه ,,

المشكلة تحدث عندما يكون أول عنصر في الـ CQ هو آخر عنصر في المصفوفة المستخدمة ,, و ذلك يحدث عندما يتم ادخال عناصر للـ CQ ثم اخراجها و بالتالي نقل مؤشر العنصر الأول في CQ إلى آخر عنصر في المصفوفة و بعدها يتم تعبئة الـ CQ من العنصر الأول من جديد و اكمال العملية كالسابق ,,

لفهم العملية بشكل أفضل انظر الى الصورتين التاليتين ,, في الأولى شكل الـ CQ و في الثانية شكل الـ Array التي تستخدم لحفظ عناصر الـ CQ ,, مع ملاحظة أن هاتين الصورتين توضحان الشكل الممكن بعد ادخال و اخراج عناصر من الـCQ بعد فترة من استخدامه ,, حيث أصبح first يؤشر على آخر عنصر في الـ CQ و last على عنصر معين بعد first,,

post-89451-1196696654_thumb.jpg

post-89451-1196696658_thumb.jpg

--- الصور رديئة لأنني لست من هواة التلوين :D ----

و المهم هنا هو first تصور أنه تم استخراج عنصر من الـ CQ و هي بهذا الشكل ,,

بالطبع,, سيكون هناك خطأ لأن مصفوفتنا لا تحتوي إلا على 9 عناصر و لا يوجد لدينا عنصر عاشر ,,

حل هذه المشكلة بأن نقوم بفحص قيمة first قبل استخراج أي عنصر ,,

أولاً للتأكد بأننا لسنا عند آخر عنصر في المصفوفة و إذا كنا عند آخر عنصر فسيكون first = 1 و الأمر الثاني بأن لا يكون last = first و معنى هذه العبارة أنه لا يوجد لدينا عناصر في الـ ْْCQ ,,

سنستخدم الدالة المساعدة في حساب next index دائماُ ,, و بالتالي هي التي تقوم بحساب العنصر التالي الذي يمكن استخدامه ,,

على كل حال أعتقد أن كلامي غير واضح كثيراُ و بإمكانك السؤال عن أي شيء إذا أردت ,,

و هذه هي طريقة حساب العنصر التالي في المصفوفة التي استخدمناها ,,

int next_index( int index ){

	int NextIndex;
	NextIndex = (Index + 1) % Capacity;

	return NextIndex;
}

حاول الاطلاع على الكود و فهمه فسيسهل لك الكثير في برمجة الـ CQ ,,

بالتوفيق إن شاء الله و لي عودة بعد أخذ فاصل طويل :thumb_up:

#12

أهلاُ من جديد ,,

ستحتاج في الغالب لبرمجة الدوال التالية كواجهة للـ CQ :

أول شيء طبعاُ هو الـ Constructor ,,

ثانياُ دالة لمعرفة إذا كانت الـ CQ فارغة أم لا ,,

دالة لمعرفة عدد العناصر الموجودة في CQ ,,

دالة الحصول على عنصر pop و دالة اخرى لإدخال عنصر push ,,

أتمنى أنني استطعت المساعدة ,,

تحياتي لك و إذا واجهت مشكلة في كتابة الكود فلا تتردد في السؤال ,,

#13

مشكور يااخ خالد على التوضيح

بس ياحبذا يكون الشرح مع الاكواد

#14

أهلاُ أخ aimn20 ,,

قم بكتابة الكود اللازم ثم سنساعدك إن كان هناك أخطاء في البرنامج ,,

لأن عملية الشرح مع الكود طويلة و لست متفرغاُ هذه الأيام ,,

تحياتي ,,

#15

ماهي هذي المشكلة بالكود لانه صراحة الدكتور بالمحاضرات مايشرح شي

على العموم انا عندي كود queue بس عادي ماهو دائري راح احطه لك

#16

لو وضعت محاولتك سيكون أفضل لك حتى تفهم البرنامج و تستفيد منه مستقبلاُ لأنه سيمر عليك كثيراُ إذا كنت تدرس البرمجة في الجامعة :resentful: ,,

تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 3 ديسمبر 2007 في 19:39

#17
#include <iostream>
#include <stdlib.h>

using namespace std;


class Queue
{
private:
	enum {MAX=10};
	int array[MAX];
	int back,front;

public:
	Queue();

	void enqueue(int e);
	int dequeue();
	bool isFull();
	bool isEmpty();
};


Queue::Queue():
back(0),front(0)
{}

void Queue::enqueue(int e)
{
	if(isFull())
	{
		cout<<"\nQueue is Full";
		exit(1);
	}

	back=(back+1)%MAX;
	array[back]=e;
}


int Queue::dequeue()
{
	if(isEmpty())
	{
		cout<<"\nQueue is Empty";
		exit(1);
	}

	front=(front+1)%MAX;
	return array[front];
}


bool Queue::isFull()
{
	if( (back+1)%MAX == front )
		return true;
	else
		return false;
}

bool Queue::isEmpty()
{
	if( back == front )
		return true;
	else
		return false;
}


int main()
{
	Queue q;
	cout<<"\nenqueue(2)";
	q.enqueue(2);
	cout<<"\nenqueue(4)";
	q.enqueue(4);
	cout<<"\nenqueue(6)";
	q.enqueue(6);

	cout<<"\nDequeue elements\n";

	cout<<"dequeue: "<<q.dequeue()<<endl;
	cout<<"dequeue: "<<q.dequeue()<<endl;
	cout<<"dequeue: "<<q.dequeue()<<endl;

	return 0;
}

تم تعديل هذه المشاركة بواسطة aimn20 في 3 ديسمبر 2007 في 19:47 — السبب: الكود غير واضح و يحتاج إلى تنسيق

#18

أعتقد أن هذا هو الكود المطلوب :clapping:

إذا كان هناك مشاكل تواجهها مع الكود أعلمنا بها ,,

تحياتي ,,

#19
Khaled.Alshaya كتب:
أعتقد أن هذا هو الكود المطلوب :clapping:

إذا كان هناك مشاكل تواجهها مع الكود أعلمنا بها ,,

تحياتي ,,

اخ خالد

يعني افهم من كلامك انه هذا هو الكود المطلوب

ولنفترض انه هو

فالكود هو مدخل قيم ثابتة من

يعني كيف اخلي المستخدم هو اللي يدخل القيم

#20

السلام عليكم ,,

أخ aimn20 طلبت المساعدة في تصميم Circular Queue و أنت لا تعرف كيف تستلم مدخلات من المستخدم عن طريق الكائن cin ,,

عجيب !!! :hmm:

#21
اقتباس
و أيضاً للأخ خلدون لي عودة للكلام و مناقشة Data Buffers في أنظمة التشغيل و كيفية جعلها Very Optimized للتسريع
أنا في الإنتظار لأن هذه المواضيع تجذبني , مع أن خبرتي فيها قليله ولكني أحب مواضع ال Optimization

تحياتي

#22
Khaled.Alshaya كتب:
السلام عليكم ,,

أخ aimn20 طلبت المساعدة في تصميم Circular Queue و أنت لا تعرف كيف تستلم مدخلات من المستخدم عن طريق الكائن cin ,,

عجيب !!! :hmm:

طيب

عديها

قول لي وشفايدة class و private

يعني اا سالني الدكتور بالمناقشة وش اقول له

#23

السلام عليكم

(انا سويت برنامج عن linked list كيف تسوي عقد وتحذق وتضيف من البدايى والنهاية واشتغل اوكي)

ممكن الكود بصراحه انا لاول مره اسمع عن ال linked list .

او يمكن انا اعرفها بس باسم اخر لذى اتمنى لو حطيت الكود الذي كتبته .

مع التحيه

#24

list.h

// list.h
// Template List class definition.
#ifndef LIST_H
#define LIST_H

#include <iostream>

using std::cout;

#include <new>
#include "listnode.h"  // ListNode class definition

template< class NODETYPE >
class List {

public:
   List();	  // constructor
   ~List();	 // destructor
   void insertAtFront( const NODETYPE & );
   void insertAtBack( const NODETYPE & );
   bool removeFromFront( NODETYPE & );
   bool removeFromBack( NODETYPE & );
   bool isEmpty() const;
   void print() const;

private:
   ListNode< NODETYPE > *firstPtr;  // pointer to first node
   ListNode< NODETYPE > *lastPtr;   // pointer to last node

   // utility function to allocate new node
   ListNode< NODETYPE > *getNewNode( const NODETYPE & );

}; // end class List

// default constructor
template< class NODETYPE >
List< NODETYPE >::List() 
   : firstPtr( 0 ), 
	 lastPtr( 0 ) 
{ 
   // empty body

} // end List constructor

// destructor
template< class NODETYPE >
List< NODETYPE >::~List()
{
   if ( !isEmpty() ) {	// List is not empty
	  cout << "Destroying nodes ...\n";

	  ListNode< NODETYPE > *currentPtr = firstPtr;
	  ListNode< NODETYPE > *tempPtr;

	  while ( currentPtr != 0 ) {  // delete remaining nodes
		 tempPtr = currentPtr;
		 cout << tempPtr->data << '\n';
		 currentPtr = currentPtr->nextPtr;
		 delete tempPtr;

	  } // end while

   } // end if

   cout << "All nodes destroyed\n\n";

} // end List destructor

// insert node at front of list
template< class NODETYPE >
void List< NODETYPE >::insertAtFront( const NODETYPE &value )
{
   ListNode< NODETYPE > *newPtr = getNewNode( value );

   if ( isEmpty() )  // List is empty
	  firstPtr = lastPtr = newPtr;

   else {  // List is not empty
	  newPtr->nextPtr = firstPtr;
	  firstPtr = newPtr;

   } // end else

} // end function insertAtFront

// insert node at back of list
template< class NODETYPE >
void List< NODETYPE >::insertAtBack( const NODETYPE &value )
{
   ListNode< NODETYPE > *newPtr = getNewNode( value );

   if ( isEmpty() )  // List is empty
	  firstPtr = lastPtr = newPtr;

   else {  // List is not empty
	  lastPtr->nextPtr = newPtr;
	  lastPtr = newPtr;

   } // end else

} // end function insertAtBack

// delete node from front of list
template< class NODETYPE >
bool List< NODETYPE >::removeFromFront( NODETYPE &value )
{
   if ( isEmpty() )  // List is empty
	  return false;  // delete unsuccessful

   else {  
	  ListNode< NODETYPE > *tempPtr = firstPtr;

	  if ( firstPtr == lastPtr )
		 firstPtr = lastPtr = 0;
	  else
		 firstPtr = firstPtr->nextPtr;

	  value = tempPtr->data;  // data being removed
	  delete tempPtr;

	  return true;  // delete successful

   } // end else

} // end function removeFromFront

// delete node from back of list
template< class NODETYPE >
bool List< NODETYPE >::removeFromBack( NODETYPE &value )
{
   if ( isEmpty() )
	  return false;  // delete unsuccessful

   else {
	  ListNode< NODETYPE > *tempPtr = lastPtr;

	  if ( firstPtr == lastPtr )
		 firstPtr = lastPtr = 0;
	  else {
		 ListNode< NODETYPE > *currentPtr = firstPtr;

		 // locate second-to-last element
		 while ( currentPtr->nextPtr != lastPtr )
			currentPtr = currentPtr->nextPtr;

		 lastPtr = currentPtr;
		 currentPtr->nextPtr = 0;

	  } // end else

	  value = tempPtr->data;
	  delete tempPtr;

	  return true;  // delete successful

   } // end else

} // end function removeFromBack

// is List empty?
template< class NODETYPE > 
bool List< NODETYPE >::isEmpty() const 
{ 
   return firstPtr == 0; 

} // end function isEmpty

// return pointer to newly allocated node
template< class NODETYPE >
ListNode< NODETYPE > *List< NODETYPE >::getNewNode( 
   const NODETYPE &value )
{
   return new ListNode< NODETYPE >( value );

} // end function getNewNode

// display contents of List
template< class NODETYPE >
void List< NODETYPE >::print() const
{
   if ( isEmpty() ) {
	  cout << "The list is empty\n\n";
	  return;

   } // end if

   ListNode< NODETYPE > *currentPtr = firstPtr;

   cout << "The list is: ";

   while ( currentPtr != 0 ) {
	  cout << currentPtr->data << ' ';
	  currentPtr = currentPtr->nextPtr;

   } // end while

   cout << "\n\n";

} // end function print

#endif

listnode.h

// listnode.h
// Template ListNode class definition.
#ifndef LISTNODE_H
#define LISTNODE_H

// forward declaration of class List 
template< class NODETYPE > class List;  

template< class NODETYPE >
class ListNode {
   friend class List< NODETYPE >; // make List a friend

public:
   ListNode( const NODETYPE & );  // constructor
   NODETYPE getData() const;	  // return data in node

private:
   NODETYPE data;				 // data
   ListNode< NODETYPE > *nextPtr; // next node in list

}; // end class ListNode

// constructor
template< class NODETYPE >
ListNode< NODETYPE >::ListNode( const NODETYPE &info )
   : data( info ), 
	 nextPtr( 0 ) 
{ 
   // empty body

} // end ListNode constructor

// return copy of data in node
template< class NODETYPE >
NODETYPE ListNode< NODETYPE >::getData() const 
{ 
   return data; 

} // end function getData

#endif

main.cpp

// main.cpp
// List class test program.
#include <iostream>

using std::cin;
using std::endl;

#include <string>

using std::string;

#include "list.h"  // List class definition

// function to test a List
template< class T >
void testList( List< T > &listObject, const string &typeName )
{
   cout << "Testing a List of " << typeName << " values\n";

   instructions();  // display instructions

   int choice;
   T value;

   do {
	  cout << "? ";
	  cin >> choice;

	  switch ( choice ) {
		 case 1:
			cout << "Enter " << typeName << ": ";
			cin >> value;
			listObject.insertAtFront( value );
			listObject.print();
			break;

		 case 2:
			cout << "Enter " << typeName << ": ";
			cin >> value;
			listObject.insertAtBack( value );
			listObject.print();
			break;

		 case 3:
			if ( listObject.removeFromFront( value ) )
			   cout << value << " removed from list\n";

			listObject.print();
			break;

		 case 4:
			if ( listObject.removeFromBack( value ) )
			   cout << value << " removed from list\n";

			listObject.print();
			break;

	  } // end switch

   } while ( choice != 5 );  // end do/while

   cout << "End list test\n\n";

} // end function testList

// display program instructions to user
void instructions()
{
   cout << "Enter one of the following:\n"
		<< "  1 to insert at beginning of list\n" 
		<< "  2 to insert at end of list\n" 
		<< "  3 to delete from beginning of list\n" 
		<< "  4 to delete from end of list\n" 
		<< "  5 to end list processing\n";

} // end function instructions

int main()
{
   // test List of int values
   List< int > integerList;
   testList( integerList, "integer" ); 

   // test List of double values
   List< double > doubleList;
   testList( doubleList, "double" ); 

   return 0;

} // end main

Chao!!!

Great place, and people, but full of sectarianism.

#25

مشكور اخي da666ni

ما قصرت والاكواد شويه غريبه على .

هل ممكن شوية توضيح او فكره على المضمون العام .

مع التحيه

مواضيع مشابهة