1.59k likes | 2.07k Views
ساختمان داده ها. متغیر : نامی است برای قسمتی از حافظه یا سلولی از حافظه . تعریف متغیرها در زبان c دو چیز را مشخص می کند . اول : این که متغیر به چه میزان حافظه نیاز دارد دوم : رشته بیتی ذخیره شده در آن حافظه چگونه تفسیر میشود .
E N D
متغیر : نامی است برای قسمتی از حافظه یا سلولی از حافظه . تعریف متغیرها در زبان c دو چیز را مشخص می کند . اول : این که متغیر به چه میزان حافظه نیاز دارد دوم : رشته بیتی ذخیره شده در آن حافظه چگونه تفسیر میشود . معمولا هر متغیر کاراکتری یک بایت،صحیح دو بایت، اعشاری چهاربایت و مضاعفdouble هشت بایت فضا را اشغال می کند که به آن سایز متغیر می گویند . برای تعریف اشاره گرها از فرمول روبرو استفاده می کنیم : نام * نوع; مثال : Char * p ;
آرایه های یک بعدی: آرایه ساده ترین ساختمان داده است که در زبان c از آن استفاده می شود. آرایه انواع مختلفی دارد ساده ترین نوع آرایه ، آرایه ی یک بعدی است . از دیدگاه تعریف آرایه مجموعه ای محدود از نوع همگن است . برای تعریف آرایه از فرمول زیر استفاده می کنیم: نوع[تعداد عناصر آرایه] نام آرایه ; مثال: Char x[10] ; آرایه ها ناحیه ی پیوسته را به خود اختصاص می دهند. برای بدست آوردن تعداد خانه های آرایه ی یک بعدی از فرمول زیر کمک می گیریم: 1+ حد پایین - حد بالا
آرایه های دو بعدی: یک آرایه ی دو بعدی از دیدگاه برنامه نویس شبیه به یک جدول است.میتوان آن را همانند آرایه ای از آرایه ها تصور کرد ، اما بر خلاف تصور برنامه نویس حافظه شکل جدولی ندارد . مثال: Char x[3][5] ; کامپیوتر می بایست دیدگاه منطقی را که حالت جدولی دارد به صورت دیدگاهی فیزیکی در آورد و آرایه را در سلول های حافظه که به صورت دنباله ای از بایت ها هستند پیاده سازی کند . بدین منظور به دو روش می تواند عمل کند روش سطری و روش ستونی. در روش سطری عناصر آرایه سطر به سطر در حافظه قرار می گیرد ودر روش ستونی عناصر آرایه ستون به ستون در حافظه ریخته می شود. محاسبه ی آدرسX[i,j] به روش سطری فرض کنید تعداد سطر های آرایه برابر با row و تعداد ستونها برابر با col باشد . روش سطری: X[i][j]=base + (I*col+i)*size روش ستونی: X[i][j]=base + (j*row+i)*size
آرایه های سه بعدی : تعداد سطر ها : row Base + (i*col +j)*size Col :تعداد ستونها H : ارتفاع Base + (k * row * col + I * col + j) * size k = h X[k][i][j] I = row J = col Base + ( l * h* row * col + k * row *col + I * col +j) * size L = t X[l][h][i][j] H = k I = row J = col
چند روش مختلف برای ذخیره سازی اعداد در آرایه های سه بعدی Base +( k+row * col +I *col +j ) *size Base +( k+row *col + j *row +i) *size Base ( i * h * col + k * col +j ) *size Base ( j * h * row +k * row + i) *size
نمایش چند جمله ای ها به کمک آرایه: چند جمله ای زیر را در نظر بگیرید می توان آنرا به کمک آرایه ها پیاده سازی کرد روشهای مختلفی برای این کار وجود دارد مثلا می توان بزرگترین درجه ای که در چند جمله ای می تواند وجود داشته باشد به عنوانMax درنظر گرفت دراین صورت می توان آرایه ای تعریف کرد که تعداد سلول های ان برابر با Max+1 باشد . 4x^5+3x^2_6x+1 5x^2-7 اگر درجه چند جمله ای را بدانیم میتوان هر جمله را در آرایه پیاده سازی کرد در واقع ضریبA[i] خواهد بود. X^(n-i) پس از ذخیره چند جمله ای ها در داخل آرایه ها می توان اعمالی مانند جمع چند جمله ای و ضرب چند جمله ای را انجام داد . حاصل جمع دو عبارت بالا 4x^5+8x^2-6x-6
روش قبل برای ذخیره سازی چند جمله ای ممکن است مناسب نباشد برای مثال چند جمله ای شما ممکن است x^1000+1 باشد . روش دیگری نیز برای ذخیره چند جمله ای ها وجود دارد دراین روش از یک آرایه با دو سطر و kستون استفاده می شود . نکته: kتعداد کل جملات تشیکل دهنده ی همه چند جمله ای هاست .
ماتریس پراکنده یا اسپارس: برای ذخیره ی یک ماتریس M*N می توان از یک آرایه ی دو بعدی باm سطر و n ستون استفادهکرد گروهی از ماتریسها وجود دارد که به آن ماتریس خلوت یا اسپارس می گوییم. در این ماتریس ها اکثریت عناصر مقدار صفر دارند . از آنجاییکه ماتریس های اسپارس در عمل وجود دارندوبرخی موارد اندازه های آنها بسیار بزرگ است می بایست روش بهینه تری را برای ذخیره آنها در کامپیوترارائه کنیم . یک روش آن است که ازیک آرایه دو بعدی با سه ستون استفاده کنیم . ستون های اول و دوم این آرایه موقعیت سطروستون مقداردر ماتریس اسپارس رانشان می دهند و ستون سوم مقدار ذخیره شده در آن سطر و ستون رانشان میدهند .(تعداد سطرهای آین آرایه به تعداد مقدار ذخیره شده در ماتریس اصلی است )
برای پیاده سازی ماتریس اسپارس میتوان از یک ساختمان کمک گرفت: Struct elements { Int row, col ,value ; {; void main() { Elements s[max]; S[0].row=0; S[0].col=0; S[0].value=7; }
ترانهاده ماتریس (ماتریس معکوس) برای بدست آوردن ترانهاده یک ماتریس باید جای سطرو ستون ها راعوض می کنیم در نتیجه عنصری که روی مکان [i][j]ازماتریس اولیه قرارداردبه مکان[j][i] درماتریس ثانویه منتقلمیشود. در ماتریس اسپارس ساده ترین راه جهت تولید معکوس آن این است که ابتدا دنبال عناصر بگردیم که در ستون صفر ماتریس قرار دارد آنها را به ترانهاده منتقل کرد به گونه ای که جای سطروستون عوض شود سپس برای ستون یک و غیره این کار انجام شود.
ساختمان : برای پیاده سازی یک ساختمان از فرمول زیر کمک می گیریم : Struct نام ساختمان { اجزای ساختمان }; مثال : Struct rect { Int x,y,s,p ; };
:Stack پشته ها یا مجموعه ایپشته مجموعه ای مرتب از چند قلم داده است که عمل درج یا حذف اقلامی یا عناصری از آن فقط از با لای پشته امکان پذیر است (مثل خشاب اسلحه). LIFO (last in first out)( (آخرین ورودی اولین خروجی در زبان Cنوع داده ای مثل پشته نداریم می بایست به وسیله ساختارهای موجود پشته را شبیه سازی کنیم به عنوان مثال می توان از یک آرایه جهت نگهداری عناصر پشته استفاده کرد.پشته ای که در آن هیچ عنصری وجود نداشته باشد پشته خالی نام دارد . بر اساس پشته ای که ارائه شد دو عمل روی پشته می توان انجام داد: 1- درج عنصرجدیددربالای پشته:به این کار Pushگفته میشود برای انجام این عمل به دوپارامترنیاز داریم یکی نام پشته ای که می خواهیم در آن درج کنیم و دوم نام عنصری که قرار است در پشته درج شود. 2-عمل حذف ازبالای پشته: که به آن Pop می گوییم، برای انجام این عمل فقط لازم است نام پشته را بدانیم.
از دیدگاه تئوری پشته یک فضای نامحدود است که می توان به هر تعداد عنصر در آن درج کنیم اما در عمل به علت محدود بودن فضا چنین چیزی امکان پذر نیست. همان طور که واضح است نمی توان از یک پشته خالی عمل حذف را انجام داد بنابراین برا ی حذف باید از خالی نبودن پشته اطمینان حاصل شود. در زبان C نوع پیش فرضی به نام پشته وجود ندارد بنابراین میبایست پشته رابا استفاده از ساختار های موجود در این زبان شبیه سازی کنیم بنابراین پیاده سازی یک ساختارپشته ای وPush, pop همگی به عهده برنامه نویس است.
:C پیاده سازی پشته در زبان برای اینکه بتوانیم پشته را به کمک آرایه پیاده سازی کنیم می بایست بدانیم که تا این لحظه چه تعداد از سلول های آرایه بوسیله پشته پرشده است بدین منظور از متغیری استفاده می کنیم که موقعیت بالاترین عنصر پشته را در آرایه به ما نشان می دهد به این متغیر Top می گویند . # Define max 100 Struct stack { : ورود عنصر جدیدTop ++ درج Char items [max] ;خروج عنصر:Top --حذف Int top; }; مقدار اولیه Top باید -1 انتخاب شود تا بتوان از تمام آرایه ها استفاده کرد بنابراین اگر (-1),top باشد به این معناست که پشته خالیست. :Empty پیاده سازی تابع این تابع در صورتی که پشته خالی باشد مقدار (1) و در غیر این صورت (0) را برگشت می زندپس تابع emptyباید از نوع INT باشد.
Int empty (stack *p) آدرس یک متغیر از نوع پشته را دریافت می کند { If (p->top==-1) Return (1); Else Return (0); } پیاده سازی تابع :Push void Push (stack *p , char x) { If (p->top == max -1) Printf (“stack is full”); Else { P->top++; P->items [p->top]=x; } }
پیاده سازی تابع Pop : char Pop (stack *p) { Char x; If (empty (p)) Printf(“stack is empty”); Else { x= p->items[p->top]; p->top- -; return (x); } }
هر تلاش برای حذف از پشته خالی منجر به وقوع رخدادی به نام پایریز(under flow) می شود و هر تلاش برایدرج در پشته پر موجب سرریز یا Overflow))می شود . کاربرد پشته ها: عبارتهای پیشوندیPrefix عبارتهای میانوندی Infix عبارتهای پسوندی Postfix برای بدست آوردن Postfix ازیک عبارت Infixباید تقدم عمگرها را در نظر داشت.ساده ترین راه برای تبدیل infix به postfixآنست که عبارت را براساس تقدم عمگرها پرانتزگذاری کنیم .سپس از پرانتزهای داخلی شروع کرده و موقعیت هر عملگر را به نزدیکترین پارانتز بسته ای که قبلا اشغال نشده جا به جا کنیم. مثال: (((A / B)-((C * D)/E))+F) infixpostfix=ab/cd*e/-f+ برای تبدیل Postfixبه Infix می توان از یک پشته خالی کمک گرفت بدین منظورازابتدای عبارت postfix شروع کرده با مشاهده هر عملوند آنرا به بالای پشته اضافه کنید و با دیدن هر عملگر دو عنصر بالای پشته را برداشته عملگر راروی آن اعمال کرده حاصل را مجددا به پشته اضافه می کنیم.
مثال: ((A * B) + C) AB * C + (A + (B / C) : ABC /+ A + B/C برای تبدیلPostfixبهInfix شبه کد زیر آورده می شود. شبه کد : برنامه ای که جزییات در آن در نظر گرفته نمی شود .
تبديل infix به prefix : (infix prefix) براي تبديل infix به prefix نيز همانند تبديل infix به postfix عمل مي كنيم فقط به جاي اينكه از ابتداي عبارت شروع كنيم از انتهاي آن آغاز مي كنيم. به مثال زير توجه كنيد: ((A+ ((B / C) *E )) - (G * H)) - + A * / BCE * GH: infix prefix تبديل prefix به infix : (prefix infix) در اين تبديل نيز همانند تبديل postfix به infix عمل ميكنيم منتهي از آخر عبارت شروع مي كنيم تا به ابتداي آن برسيم.به مثال زير توجه كنيد: + * ABC prefix infix: A * B+C
یک رشته خالی است s While (به انتهای رشته ورودی نرسیده ای ) { Symb = نماد بعدی در رشته ورودی; If (یک عملوند است symb ) Push (s , symb ); Else { Op2 = pop (s); Op1 = pop (s); Push (s , op1 symb op2 عبارت حاصل از); } }
شبه کد تبدیلprefix به infix: یک رشته خالی است s While (به ابتدای رشته ورودی نرسیده ای ) { Symb = نماد قبلی در رشته ورودی; If (یک عملوند است symb ) Push (s , symb ); Else { Op2 = pop (s); Op1 = pop (s); Push (s , op2 symb op1 عبارت حاصل از); } }
شبه کدی برای تبدیل infix به Postfix از ابتدای عبارت infix شروع کرده و با دیدن هر عملوند آنرا درخروجی چاپ می کنیم و با دیدن هر عملگر آنرا به پشته اضافه می کنیم به شرطی که تقدم عملگر موجود در بالا کمترازعملگر مشاهده شده باشد در غیر این صورت عملگر های موجود درپشته را آنقدر Pop می کنیم و چاپ می کنیم . تا زمانی که به پشته خالی برخورد کنیم یا با عملگرتقدم کمتری برخورد نماییم دراین لحظه عملگرمشاهده شده را به پشته می افزاییم و پس از رسیدن به انتهای عبارت عملگرهای موجود در پشته را یکی یکی Pop کرده و مشاهده می کنیم . مثال دیگری از کاربرد پشته ها: فرض کنید بخواهید یک عبارت شامل پرانتز گذاری ها را از نظر صحت بررسی کنید بدین منظور می توان از ابتدای عبارت شروع کرد و با مشاهده هر پرانتز باز یک واحد اضافه و پرانتز بسته یک واحد کم نمود . (1(2A + (3B / C2)* E1)-F0) (1A + B0)-1) شرایط زیراگر برقرار باشد عبارت معتبر است: اولا : در خاتمه می بایست صفر به دست آید. ثانیا : در طول مسیر هیچ گاه شماره منفی دیده نشود.
اما فرض کنید عبارت شما به جزپرانتز شامل کروشه و آکولاد بوده باشد در این صورت شماره گذاری کمکی نخواهد کرد . ساده ترین روش جهت تست چنین عبارتی استفاده از پشته است . {A*(B+C)} جهت بررسی عبارتی که به جز پرانتز ازمحدود کننده های دیگرمانند کروشه یا آکولاد کمک می گیرند از پشته استفاده می کنیم . پیمایش عبارت را از ابتدای عبارت اغاز می کنیم.با دیدن هر باز کننده آنرابه بالای پشته اضافه می کنیم وبا مشاهده هرخاتمه دهنده یک نمادازبالای پشته حذف می کنیم نماد حذف شده می بایست با باز کننده ای که مشاهده شده مطاقبت داشته باشد. شرایط غلط بودن عبارت: 1-خاتمه دهنده با عنصر بالای پشته مطابقت نداشته باشدمثال: ({ )} 2-در طول پیمایش عبارت مجبور باشیم از پشته خالی حذف کنیم مثال :}(({ }) 3-پس از خاتمه پیمایش پشته خالی نشده باشد مثال: {( )})
شبه کدی برای بررسی صحت عبارت : یک رشته خالی است s V = 1 ; While (به انتهای رشته نرسیده ای) { Symb = نماد ورودی بعدی ; If ( symb == ‘)’ || symb == ‘[’ || symb == ‘{‘) Push(s,symb); If ( symb == ‘)’ || symb == ‘]’ || symb == ‘}’) { If (empty (s)) { V = 0 ; Break ; } Else { Symb 2 = pop (s) ;
If ( !match (symb, symb 2)) دونماد را از نظر هم گروه بودن چک کندmatchفرض کنیم { V = 0 ; Break; }//Else }//if }//while If (!empty (s)) V = 0 ; If (v == 0) Printf (“ عبارت غلط است”); Else Printf (“عبارت صحیح است”); }
صف: صف مجموعه اي ازعناصر مرتب است كه هرعنصر از ابتداي صف حذف شده و در انتهاي صف درج مي شود. FIFO (First In First Out) به صف نيز Queue گفته مي شود. از آنجا كه درج صف ازدوطرف انجام مي شود مي بايست موقعيت عنصرابتدا وانتهاي صف را بدانيم معمولا به عنصر ابتدا Front (F) و به عنصر انتهاي صف Rear ( R ) گفته مي شود.
اعمال ابتدايي روي صف: نيز گفته مي شود. براي انجام عمل درج معمولا به دو پارامتر Insert1-عمل درج در صف كه به آن . نيازمنديم الف) صفي كه قرار است در آن عنصر جديد درج شود. ب) عنصر جديد كه قرار است وارد صف شود. گفته مي شود ،اين عمل در صورت خالي نبودن صف Remove2-عمل حذف از صف كه به آن به يك عمل نياز داريم آن هم نام صف است..Remove عنصر اول را حذف مي كند،براي انجام عمل صف نيز مانند پشته فضايي نامحدود تصور مي شود كه در عمل به علت نامحدود بودن فضا اين گونه نيست بنابراين بايد در نظر گرفت كه تعداد اقلام درج شده در صف باعث سرريز نشود همچنين واضح است كه از يك صف خالي نمي توان حذف كرد چون منجــر به پا ريز مي شود.
: Cپياده سازي صف در زبان براي پياده سازي صف از يك آرايه كمك مي گيريم .جهت نگهداري موقعيت ابتدا و انتهاي صف دو در آرايه استفاده مي كنيم . F,R متغير به نام هاي # Define Max 100 Struck Queue { Char Items [Max]; Int f, r; }; :Insertپياده سازي تابع Void Insert (Queue *q, Char x) { If (q r == Max-1) Print f ("Queue is full "); Else { q r ++; q Items [q r] =x; } }
:Removeپياده سازي تابع Char Remove (Queue *q) { Char x; If (empty (q)) Print f ("Queue is empty"); Else { X=qItems [qf]; qf++; Return(x); } }
:Empty پياده سازي تابع Int empty (Queue *q) { If (q f >q r) return (1); else return (0); } صف به شكلي كه پياده سازي شد يك ايراداساسي دارد وآن اين است كه پس از تعدادي عمل درج و به آخرين انديس آرايه رسيده باشدوعلي رغم خالي بودنrحذف ممكن است به حالتي برخورد نتوان عنصر ديگري به صف اضافه كرد .F خانه هاي قبل از به آخرين انديس تمامي rبراي حل اين مشكل راه حل هايي وجود دارد مثلا مي توان لحظه ي رسيدن عناصررابه ابتداي آرايه منتقل كرد يا اينكه با هر بارعمل حذف عناصر صف يك واحد به سمت چپ است راه حل بهتر استفاده Shift انتقال داده شود هــردو پيشنهاد مستلزم تعداد بسيار زيادي عمل از صف هاي دايره اي است .
صف هاي دايره اي (چرخشي): Max [i]دريك صف چرخشي با آرايه به گونه اي رفتار مي شود كه به نظر مي رسد سلول انديس قبل از سلول انديس صفر قرار گرفته است در اين صورت تمامي اصولي كه در صفهاي خطي گفتيم نمي تواند نشان دهنده ي خالي بودن صف f>r ميبايست اصلاح شود در صف های دایره ای شرط نشان دهنده پر بودن صف نيست تعداد عناصر داخل صف نيز R==max-1 باشد همچنين شرط به دست آيد .R-f+1 نمي تواند از رابطه F,Rدر نظر مي گيريم يعني زماني كه صف خالي است F==Rشرايط خالي بودن صف را به صورت به خانه ي واحدي مراجعه مي كند در اثر اين عمل مشكلي پيش مي آيد و آن اين است كه اگـــر آرايه برابر خواهدبود براي پيشگيري ازچنين مشكلي فرض مي كنيم كه خانه متعلق F باR شودكاملا پر همواره بايد خالي باشد . Fبه
:Insertپياده سازي تابع Void Insert (Queue *q , Char x ) { If ((qr+1) % Max ==q f) Print f ("Queue is full "); Else} q r =(qr+1)% Max ; q Items [q r] =x; } : Emptyپياده سازي تابع Int empty (Queue *q) { if (q f == q r) Return (1); Else Return (0); }
: Removeپياده سازي تابع Char Remove (Queue *q) { Char x; If (empty (q)) Print f ("Queue is empty”); Else { q f=(qf+1)%Max; x=q Items [qf]; Return (x); } }
صف اولويت: نيست . در اين صفها تربيت خروج بر اساس Fifo به صورتدر صف اولويت تربيت ورود و خروج اولويت عناصر است از ديدگاهي ساده تر مي توان صفها ي اولويت را به دو شکل صف اولویت صعودي وصف اولويت نزولي دسته بندي كرد. در صف اولويت صعودي عناصر مي توانند به هرترتيبي واردشونداما عمل حذف يك عنصر همواره روي عناصر كوچك تر انجام مي پذيرد . درج و حذف در صف اولويت صعودي: : عنصر جديد در انتهاي صف درج مي شود . (یک عمل)1-درج مقایسه) nحذف : با جستجو در صف كوچكترين عنصر پيدا شده و حذف مي شود . ( مقایسه)n/22-درج : عنصر جديد در محل منطقي اش (به كمك جست و جو ) درج شود .( حذف : از ابتداي صف (یک عمل) نکته : از نظر تعداد مقايسات روش دوم از روش اول بهتــر است . مثال: 4 2 9 6 8 1 روش اول : 4 2 9 6 8 1 روش دوم : 1 2 4 6 8 9
نکته ا ی راجع به پیاده سازی پشته ها در آرایه ها: می توان با استفاده از یک آرایه دو پشته را پیاده سازی کرد در این صورت پشته اول از چپ به راست و پشته دوم از راست به چپ در آرایه قرار می گیرد . شرط خالی بودن پشته اول : top1 == -1 شرط خالی بودن پشته دوم : top2 ==max : شرط پر بودن هردو پشته Top1 + 1 == top2 x=Items[top1] x=Items [top2]; حذف از پشته دوم حذف از پشته اول top1--; top2++; top1++; top2--; درج در پشته دوم درج در پشته اول Items[top]=x ; Items[top]=x;
در یک آرایه می توان چندین پشته را پیاده سازی کرددراین صورت می بایست آرایه را تقسیم بر تعداد پشته ها کنیم فرضا اگر آرایه 20 سلول دارد و تعداد پشته ها n=4 است هر پشته 5 خانه از آرایه را اشغال خواهد کرد . max b [i] = i * [max/n]تعداد سلول های آرایه تعداد پشته هاn top [i] = i * [max/n]-1 هر پشته max/n سلول اشغال می کند.
در یک آرایه می توان چندین پشته را پیاده سازی کرددراین صورت می بایست آرایه را تقسیم بر تعداد پشته ها کنیم فرضا اگر آرایه 20 سلول دارد و تعداد پشته ها n=4 است هر پشته 5 خانه از آرایه را اشغال خواهد کرد . max b [i] = i * [max/n]تعداد سلول های آرایه تعداد پشته ها n top [i] = i * [max/n]-1 هر پشته max/n سلول اشغال می کند.
ليست هاي پيوندي: مشكل بزرگ آرايه ها آن است كه جهت پياده سازي ساختارهايي مثل صف و پشته نمي دانيم كه دقيقا چند سلول از حافظه مورد نياز است پس مجبوريم حداكثــر برآورد رادرانتخاب تعداد عناصر آرايه اعمال كنيم اين كار باعث مي شود كه در بسياري از موارد حافظه هــدر رود و بلااستفاده باقي بماند يكي از راه كارهاي از بين بردن اين مساله استفاده از ليست هاي پيوندي است . فرض كنيد عناصر پشته و يا صف ،در داخل خودشان آدرس عنصر بعدي را داشته باشند چنين ترتيبي يك ساختمان داده اي به نام ليست پيوندي خطي راايجاد مي كند هريك ازعناصرتشكيل دهنده ليست و یا گره نام دارد .Node پيوندي شكل ساده اي از يك گــره : : اطلاعات مورد نظر ما را نگه داري مي كند infoبخش : يك اشاره گر است كه به گره ي بعدي در ليست پيوندي اشاره مي كند .Nextبخش يك ليست پيوندي خطي معمولا به شكل زير است:
براي دسترسي به ليست پيوندي از يك اشاره گر خارجي به اولين گره در ليست پيوندي اشاره مي كند استفاده مي كنيم. يا تهي دارد اين بدان معنا است كه پس از اين گره ،گره Null نكته:اشاره گر در آخرين گره مقدار ديگري در ليست پيوندي وجود ندارد. نكته: براي پياده سازي گره مي توان از يك ساختمان كمك گرفت به عنوان مثال ساختمان زير گره اي است.Char در آن از نوع infoرا تشريح مي كند كه بخش Struck node { Char info; Node *next; }; ) در گره را مشخص مي كند و منظور Info (قسمت اطلاعاتيpinfo اشاره گر به گره باشد pاگر اشاره گري است كه در آن گره خارج مي شود. P next از فرض كنيم خواسته باشيم گــره را به ليست پيوندي اضافه كنيم برا ي اين كار ابتدا مي بايست گره وجود دارد كه وظيفه ي ايجاد گره ي جديد Get nodeجديدي را ايجاد كنيم فرض كنيد تابعي به نام آن را مقداردهي Info , Next و توليد آدرس آن را به عهده دارد پس از ايجاد گره جديد بخش هاي مي كنيم.
P=get node ( ); Pinfo=x; Pnext=list; List=p; پياده سازي تابع Get node : در زبان C تابعي وجود دارد به نام malloc كاربرد اين تابع بدين صورت است كه به اندازه عدد ذكر شده درپرانتزجلوي آن حافظه رابه شمااختصاص مي دهد براي اينكه بتوانيم بتوانيم به اندازه ی يك گره فضا بگيريم از اين تابع به شكل زير استفاده مي كنيم. Malloc (size of (node)) فضاي اختصاص داده شده مي بايست در قالب يك گره پيكربندي شود بدين منظور مي بايست بنويسيم: Node *malloc (size of (node)) *ذكــر شده جلوی node بدين خاطر است كه آدرس حافظه ي اختصاص داده شده توليد شده و نهايتا به وسيله ي تابع Get node برگشت داده شودشکل تابع get node براساس آنچه گفته شدبه صورت زیر است:
Node *get node( ) { Return ((node *) malloc (size of (node)) } حذف يك گره از ابتداي ليست پيوندي : P=list; List=list next; list X=pInfo; Free (p); پياده سازي پشته ها با استفاده از ليست هاي پيوندي خطي: عمل افزودن يك عنصر به ابتداي ليست پيوندي مانند اضافه كردن عنصري در بالاي پشته است و عمل حذف اولين عمل عنصر از لیست پيوندي مانند حذف عنصر بالاي پشته مي باشد بنابراين توابع push , pop را مي توان به شكل زير پياده سازي كرد. ابتدا تابع empty را طراحي مي كنيم.
پياده سازي تابعEmpty: Int empty (node *p) { If (p==Null) Return (1); Else Return (0); }
پياده سازي تابع Push: Void push (node *list, char x) { Node *p; P=Get node (); Pinfo=x; P next=list; list=p; }
پياده سازي تابع Pop: Char pop (node *stack) { Node *p; Char x; If (empty (stack)) Print f ("stack is empty"); Else { P=stack; stack = stack next; x=pinfo; Free (p); Return (x); } }
پياده سازي صف ها به كمك ليست ها ي پيوندي خطي : اگر ليست پيوندي خطي به گونه اي مديريت شود كه اولين عنصر ورودي ، اولين عنصر خروجي باشد مي توان گفت يك صف پياده سازي شده است در نتيجه مجبوريم از يك طرف ليست پيوندي عمل حذف و در طرف ديگر آن عمل درج را انجام دهيم.
پياده سازي تابع Insert: Void Insert (node *p , char x) { P=Get node (); Pinfo=x; P next=Null; If (r==Null) { f=P; r=P; } Else { r next=P; r =P; } }
پياده سازي تابعRemove: Char Remove (node *p ) { Char x; If (f==Null) Print f ("Queue is empty"); Else { P=f; f=f next; X=pinfo; Free (p); If (f==null) f=null; Return (x); } }
معايب پياده سازي صف و پشته با استفاده از ليست هاي پيوندي: -1هر گره در ليست پيوندي از هر سلول آرايه فضاي بيشتري تلف مي كند. -2مديريت ليست هاي پيوندي نسبت به آرايه مشكل تر است. به طور كلي ليست ها پيوندي و آرايه ها را مي توان مورد ارزيابي قرار داد. مزاياي ليست پيوندي نسبت به آرايه ها : علاوه بر آنچه كه گفته شد در ليست هاي پيوندي درج و حذف از ميا نه ي ليست پيوندي به سادگي امكان پذير است اما در آرايه ها هر عمل درج و هر عمل حذف نياز به Shift دادن عناصر آرايه دارد مزاياي آرايه نسبت به ليست پيوندي : علاوه بر آنچه که گفته شد دسترسي به هر يك از عناصر آرايه به شكل مستقيم انجام مي شود اما در ليست های پيوندي براي رسيدن به گره nام مي بايست n-1 گره پشت سر آن پيمايش شده باشد .
شبه كدي بنویسید كه در يك ليست پيوندي اگر pبه گره اي اشاره كــرده با شدگره بعداز آن را حذف كند: Delafter (p) { If (pnext ==Null) Print f ("can not remove ") Else { q=pnext; Pnext=qnext; Free (q); } } p B C D E A q