670 likes | 1.68k Views
جلسه ششم. به نام خداوند هستی بخش یگانه. لیست پیوندی. Linked List. A.M. Safaei. جلسه ششم. لیست پیوندی. لیست پیوندی استفاده از اصطلاح ( لیست) در زندگی روزمره به یک مجموعه خطی از اقلام داده ای گفته می شود که دارای عنصر اول ، دوم ، ... و عنصر آخر است که عنصری به لیست اضافه یا حذف می شود.
E N D
جلسه ششم به نام خداوند هستی بخش یگانه لیست پیوندی Linked List A.M. Safaei
جلسه ششم لیست پیوندی • لیست پیوندی • استفاده از اصطلاح ( لیست) در زندگی روزمره به یک مجموعه خطی از اقلام داده ای گفته می شود که دارای عنصر اول ، دوم ، ... و عنصر آخر است که عنصری به لیست اضافه یا حذف می شود. • معمولا برای ذخیره اطلاعات و پیاده سازی الگوریتم از دو ساختار: آرایه و لیست پیوندی استفاده می کنیم. • لیست پیوندی ساختمان داده ای است که اندازه آن بصورت پویا تغییر می کند یعنی در هنگام اجرای برنامه می توان به اندازه دلخواه، حافظه در اختیار بگیریم. • ذخیره ، بازیابی و پردازش داده ها از اعمال رایج در لیست می باشد. • انواع لیست پیوندی : 1- لیست پیوندی خطی 2- لیست پیوندی عمومی 3- لیست پیوندی حلقوی 4- لیست پیوندی دو طرفه
[0] [1] [2] array آرایه A B C لیست پیوندی linked A B C جلسه ششم لیست پیوندی • برخی تفاوت های آرایه و لیست پیوندی • آرایه یک روش ذخیره داده می باشد که دارای معایبی زیر می باشد. • بازگشت ناپذیر بودن حافظه بعد از گرفتن آن • لازم بودن پیش بینی بیشترین حافظه مورد نیاز • پر هزینه بودن حذف و اضافه عناصر در آرایه ( مستلزم شیفت (جابجائی) عناصر است) • جستجو و مرتب سازی در آرایه ها سریع تر و راحتر از لیست پیوندی انجام می شود. زیرا جستجو در آرایه ها به دو صورت خطی و باینری انجام می شود در حالی که در لیست پیوندی فقط بصورت خطی (ترتیبی) انجام می شود.
جلسه ششم لیست پیوندی • آرایه ها از حافظه ایستا استفاده می کنند و لیست پیوندی از حافظه پویا. یعنی اگر در اجرای برنامه تعداد کمی از خانه های آرایه استفاده شود اتلاف حافظه خواهیم داشت و اگر بخواهیم بیش از حافظه تخصیص داده شده استفاده کنیم امکان پذیر نیست. • پر هزینه بودن حذف و اضافه عناصر در آرایه ( مستلزم شیفت (جابجائی) عناصر است) • می خواهیم C را به آن اضافه کنیم به طوری که ترتیب آن الفبایی بماند. 0 1 2 3 4 5 Shift 0 1 2 3 4 5
node جلسه ششم لیست پیوندی • لیست پیوندی • هر عنصر لیست پیوندی را گره (node) می نامیم که دارای حداقل دو فیلد؛ فیلد داده و دیگری فیلد آدرس که به عنصر بعدی در لیست پیوندی اشاره می کند. • تعریف یک گره : struct Node { elementtype info; Node *next ; }
جلسه ششم لیست پیوندی • لیست پیوندی خطی ( یک طرفه ، زنجیر) • لیستی است که در آن هر گره علاوه بر اطلاعات مورد نیازش آدرس گره بعدی را نیز در اختیار دارد. • فیلد آدرس آخرین گره به Null اشاره می کند که نشان دادن عنصر آخر لیست می باشد. • برای دسترسی به یک لیست خطی باید آدرس سر لیست ( اولین گره لیست) را داشته باشیم. • معمولا آدرس سرلیست را با head, first, start و یا L (مخفف List) نشان می دهند. first 12 4 10 7 Null • مراجعه به گره های لیست : اگر first یک اشاره گر به گره ای از لیست باشد first info مراجعه به فیلد آدرس اطلاعات همان گره مراجعه به فید آدرس گره بعدی first next
جلسه ششم لیست پیوندی • پیمایش لیست پیوندی • به منظور دستیابی به تمام عناصر لیست و پردازش آنها صورت می گیرد. • برای عمل پیمایش باید از یک اشاره گر کمکی (مثل P) استفاده کنیم که اشاره گر سرلیست (first) از دست نرود. • جهت حرکت اشاره گر P از دستور : P=P next • الگوریتم پیمایش لیست خطی: first Null P first Null P • P=first; • while (P !=Null) • { • process (Pinfo); • P=P next; • }
جلسه ششم لیست پیوندی • افزودن گره به ابتدای لیست پیوندی • برای افزودن داده جدید به لیست پیوندی 4 عمل اصلی انجام می گیرد: 1- تشکیل گره جدید بر اساس اطلاعات جدید افزوده شدنی 2- بدست آوردن آدرس گره ای که باید قبل از گره جدید قرار گیرد (P) 3- آدرس گره جدید که به محل اشارگر Pاشاره می کند. 4- آدرس گره P را به محل گره جدید تغییر می دهیم.
جلسه ششم لیست پیوندی اضافه کردن به ابتدای لیست A newNode first 0 B C D E 0 newNode=getnode() newNode link = first; first = newNode;
newNode first 0 A B C D E جلسه ششم لیست پیوندی • اضافه کردن به ابتدای لیست (ادامه) newNode =getnode ( ); newNode info=A; newNode next=first; first= newNode;
جلسه ششم لیست پیوندی • مثال : می خواهیم گره ای با مقدار 6 را به ابتدای لیست زیر اضافه کنیم • ابتدا با استفاده از عملگر getnode ( ) یک گره خالی ایجاد می کنیم و آدرس آن را در P قرار می دهیم. 2 3 5 first Null P = getnode ( ) ; P P info =6 ; 6 0 P با دستور P next = first قسمت اشاره گر P را به ابتدای لیست first وصل می کنیم. first 6 2 3 5 P Null حال first=P باعث می شود first به ابتدای لیست اشاره کند. 6 3 2 5 first Null P =getnode ( ); P info=6; P next=first; first=P; P
جلسه ششم لیست پیوندی • پیاده سازی تابع getnode ( ): • در زبان C تابعی وجود دارد به نام malloc كاربرد این تابع بدین صورت است كه به اندازه عددذكر شده درپرانتزجلوی آن، حافظه را اختصاص می دهد برای اینكه بتوانیم به اندازه ییك گره فضا بگیریم از این تابع به شكل زیر استفاده می كنیم. Malloc (size of (node)) • فضای اختصاص داده شده می بایست در قالب یك گره پیكربندی شود بدین منظور می بایست بنویسیم: Node *malloc (size of (node)) • ستاره (*) ذكــر شده جلوی node بدین خاطر است كه آدرس حافظه ی اختصاص داده شده تولید شده و نهایتا به وسیله ی تابع getnodeبرگشت داده . Node *get node( ) { return (node *malloc (size of (node)) }
جلسه ششم لیست پیوندی • افزودن گره ای به بعد از گره ای با آدرس معلوم • گره ای با مقدار C بعد از گره ای با آدرس P درج می کنیم p first 0 A B D E C newNode newNode=getnode( ); newNode info = C; newNode next = pnext; p next = newNode;
جلسه ششم لیست پیوندی • حذف اولین گره • مراحل کار: 1) تنظیم اشاره گرها 2) حذف کردن گره (آزاد کردن حافظه) p=first; first ِA ِB C ِD 0 p first = p next p ِA ِB C ِD 0 first free node(p) first ِB C ِD 0
جلسه ششم لیست پیوندی • حذف گره ای که آدرس گره قبلی آن در دسترس است • مراحل کار: 1) یافتن گره قبل از گره مشخص شده برای حذف(T) 2) تغییر جای اشاره گرها 3) حذف گره P • می خواهیم گره با آدرس P را که بعد از گره با آدرس T است حذف کنیم p T first ِA ِB C ِD 0 p T T next = p next first ِA ِB C ِD 0 free node (p); T first ِA ِB ِD 0
جلسه ششم لیست پیوندی • الگوریتم حذف گره ای که آدرس گره قبلی آن در دسترس است void delete (Node *T, Node *P) { if (P==Null) { count << “ List is Empty”; exit (1); } T next = p next; free node(P); }
جلسه ششم لیست پیوندی • تمرین • الگوریتم پیمایش ، درج به ابتدای لیست و درج در آدرس معلوم ، حذف از ابتدای لیست و حذف از آدرس معلوم لیست پیوندی را نوشته.
جلسه هفتم لیست پیوندی • لیست هایی با گره رأس • در برخی از لیست ها ممکن است یک گره اضافی که عضوی از لیست پیوندی محسوب نمی شود در ابتدای لیست قرار گیرد که آن را گره رأس می نامند. معمولا در قسمت داده این گره برای اطلاعات کنترلی نظیر تعداد گره های لیست پیوندی استفاده می کنند. • همانگونه که در درج و حذف گره ها باید دو حالت در نظر گرفته شود: یک حالت برای درج و حذف از ابتدای لیست و حالت دیگر درج و حذف بعد از گره اول، گره راس موجب می شود که گره اول نیز دارای گره قبلی باشد لذا برای درج و حذف دیگر نیازی نیست که دو حالت در نظر گرفته شود. first ِ3 ِA B ِC 0 گره رأس (حاوی تعداد گره های لیست )
جلسه هفتم لیست پیوندی • پیاده سازی گره رأس • بخش Info درگره راس دربرخی موارد اطلاعاتی از لیست پیوندی در گره قرار می گیرد مثلا می توان تعداد گره های لیست و اشاره گر به ابتدای لیست را قرار داد و در برخی موارد گره راس می تواند دو اشاره گر یكی به ابتدا و دیگری به انتها ی لیست پیوندی داشته باشد. struct Node { elementtype info; Node *next; }; structcharstr { int length; Node *firstchar; }; charstr S1,S2; • مرتبه اجرائی عمل حذف و اضافه در لیست های پیوندی : O(1)
جلسه هفتم لیست پیوندی • لیست های پیوندی حلقوی ( چرخشی ) • لیست پیوندی حلقوی همانند لیست پیوندی یکطرفه است با این تفاوت که فیلد آدرس آخرین گره آن بجای آنکه به NULL اشاره کند به گروه اول لیست (سرلیست) اشاره می کند. • مزیت این لیست بر لیست خطی این است که با داشتن آدرس هر گره دلخواه می توان به کلیه گره های لیست پیوندی دسترسی داشت، در حالی که در لیست پیوندی خطی می بایست آدرس سرلیست را در اختیار داشته باشیم. • برای آنكه مدیریت لیست ساده تر انجام شود اشاره گر خارجی به لیست را روی آخرین گره فرض می گیریم در نتیجه گره بعد از آن گره اول خواهد بود. P info اطلاعات آخرین گره لیست اشاره می کند P next به اولین گره لیست اشاره میکند P
جلسه هفتم لیست پیوندی • الگوریتم اضافه کردن گره در ابتدا یا انتهای لیست های پیوندی حلقوی void AddNode( Node *endp , elementtype item ) { Newp = getnode () ; Newp info = item ; if (endp = = NULL) { endp = Newp; Newp next = Newp } else { Newp next = endp next; endP next = Newp; } } • فرض می کنیم endP به انتهای لیست حلقوی اشاره کند endP
جلسه هفتم لیست پیوندی تمرین • معنای P = P next در یک لیست حلقوی ؟ • اشاره گر را در لیست حرکت می دهد • اشاره گر را به گره اول در لیست حرکت می دهد • اشاره گر را به گره بعدی در لیست حرکت می دهد • مقدار Null را در P قرار می دهد P
جلسه هفتم لیست پیوندی • لیست های پیوندی دوطرفه (لیست های دو پیوندی) • لیستی است که در آن هر گره علاوه بر اطلاعات مورد نیاز دارای دو پیوند است که به وسیله آنها می تواند هم به گره بعدی و هم به گره قبلی خود دسترسی داشته باشد. • یکی از مزایای لیست های دو پیوندی امکان پیمایش معکوس لیست می باشد. پیوند به گره قبلی پیوند به گره بعدی Null Null • در بعضی از کتابها بجای right از next یا rlink و بجای left از prev یا llink استفاده شده است.
جلسه هفتم لیست پیوندی • لیست های پیوندی دوطرفه (لیست های دو پیوندی) • ساختار گره در لیست دو پیوندی struct Node { Node *left; Elementtype info; Node *right; }; Null Null • لیست های دو پیوندی را می توان به صورت حلقوی نیز پیاده سازی نمود
جلسه هفتم لیست پیوندی • الگوریتم افزودن گره ای به بعد از گره ای با آدرس مشخص • جهت درج گره جدید در لیست دوپیوندی شامل تنظیم پیوندهای روبه جلو و روبه عقب است تا به گره های قبل و بعد اشاره کند. سپس باید پیوند روبه جلوی گره قبلی و پیوند رو به عقب گره بعدی را طوری تنظیم کرد که به گره جدید اشاره کنند. • می خواهیم گره ای را بعد از گره ای با محتویات a درج کنیم. • با استفاده از تابع getnode یک گره جدید ایجاد می کنیم. • قسمت Info گره جدید را مقدار دهی می کنیم. • آدرس گره a را در فیلد چپ گره جدید جایگذاری می کنیم • آدرس فیلد راست گره a را در فیلد راست گره جدید قرار می دهیم. • آدرس گره جدید را در فیلد چپ گره بعد از a جایگذاری می کنیم. • آدرس گره جدید را فیلد راست گره a قرار می دهیم.
جلسه هفتم لیست پیوندی void Insert( Node *perP , elementtype b ) { Node *Newp ; Newp = getnode() ; if ( IS_FULL(Newp) ){ cout<<" The memory is full"; exit(1); } Newp info = b; newP left = PreP; newP right = PreP right; PreP right left = newP; Pre P right = newP; } • می خواهیم گره ای را بعد از گره ای با محتویات a درج کنیم. • با استفاده از تابع getnode یک گره جدید ایجاد می کنیم. • قسمت Info گره جدید را مقدار دهی می کنیم. • آدرس گره a را در فیلد چپ گره جدید جایگذاری می کنیم • آدرس فیلد راست گره a را در فیلد راست گره جدید قرار می دهیم. • آدرس گره جدید را در فیلد چپ گره بعد از a جایگذاری می کنیم. • آدرس گره جدید را فیلد راست گره a قرار می دهیم. b PreP newP
جلسه هفتم لیست پیوندی • الگوریتم حذف گره ای با آدرس مشخص • فرض کنید می خواهیم گره با مقدار b که اشاره گر P به آن اشاره می کند را از لیست حذف کنیم. • در فیلد چپ گره بعد از گره b آدرس گره چپ گره b را قرار می دهیم • در فیلد راست گره قبل از گره b آدرس گره راست گره b را قرار می دهیم. • مقدار حافظه اختصاص داده شده را به P را آزاد می کنیم. void Delete (Node *P) { P right left = P left; P left right= P right; freenode (P); }; P • پیچیدگی زمانی عمل درج وحذف در لیست دو طرفه با زمان O(1) انجام می شود. • مرتبه اجرائیی جستجو در لیست دو طرفه برابر با O(n) می باشد.
جلسه هفتم لیست پیوندی • تمرین • هنگام حذف یک گره از لیست دو طرفه چند آدرس جابجا می شود؟ • دو آدرس ؛ فیلد اشارگر right گره ماقبل و فیلد اشاره گر left مابعد گره ای که می خواهد حذف شود. • هنگام درج گره در لیست دو طرفه چند آدرس تغییر می کند؟
جلسه هفتم لیست پیوندی • پیاده سازی پشته با لیست پیوندی • با توجه به اینکه پشته ساختاری است که فقط از یک طرف می توان به عناصر آن (بالای پشته) دسترسی داشت، اگر در یک لیست پیوندی اعمال حذف و اضافه یک گره را از ابتدای لیست (سرلیست) انجام دهیم می گوییم ساختار این لیست پیوندی همانند پشته می باشد (به این ساختار پشته های پیوندی نیز گفته می شود). • یکی از معایب پیاده سازی پشته و صف با استفاده از آرایه این است که اندازه ثابت آرایه ، اندازه پشته و صف را محدود می کند. X Top struct Node { elementtype info; struct Node *next; } Node *top; 0
جلسه هفتم لیست پیوندی • افزودن به پشته ( Push) Top ptr void push (Node *top, elementtype item) { ptr = getnode( ); if ( IS – FULL (ptr)) { count << “ the memory is full”; exit (1); } Ptr info = item; Ptr next = top; top = ptr; } item Top 0
جلسه هفتم لیست پیوندی • حذف از پشته ( Pop) Top ptr void pop (Node *top) { if ( top == Null) { count << “ stack is empty”; exit (1); } Node *ptr; ptr = top; Top = top next; freenode (ptr); } item Top 0
جلسه هفتم لیست پیوندی • پیاده سازی صف با لیست پیوندی • اگر در لیست پیوندی آدرس گره اول front و آدرس گره آخر rear را داشته باشیم و همواره عمل حذف را از ابتدا و عمل درج را به انتهای آن لیست انجام دهیم، یک صف پیوندی پیاده سازی کرده ایم، در این ساختار دارای دو اشاره گر front و rear می باشیم که به ابتدا و انتهای لیست پیوندی اشاره می کند. front rear Null structqueue { elemnttypeinfo; queue *next; }; queue *front,*rear; پیاده سازی صف با استفاده از لیست پیوندی
جلسه هفتم لیست پیوندی • افزودن به صف پیوندی • همانطور که می دانیم عمل اضافه کردن به صف پیوندی می بایست از انتهای صف صورت می گیرد، می خواهیم گره ای را به انتهای لیست پیوندی اضافه کنیم، اگر rear به آخرین گره لیست اشاره کند، الگوریتم زیر گره ptr را به آخر صف پیوندی اضافه می کند: void Add(Node *rear , elementtype item ) { ptr = getnode(); if ( IS_FULL(ptr) ) { cout<<" The memory is full " ; exit(1) ; } ptr info = item; ptr next= NULL; rear next = ptr; rear= ptr; }
جلسه هفتم لیست پیوندی • حذف از صف پیوندی • همانطور که می دانید عمل حذف از صف از سر صف امکانپذیر می باشد. اولین گره صف را حذف می کنیم. void Delete(Node *front ) { Node *ptr; ptr = front; front = front next; freenode (ptr); } front front rear Null ptr
جلسه هفتم لیست پیوندی • لیست عمومی • لیست عمومی یک لیست پیوندی است که فیلد اطلاعات گره های آن می تواند بر حسب نیاز اشارهگر باشد، ساختار هر گره این نوع لیست به صورت زیر است: • انواع گره در لیست عمومی: • Tag نشان دهنده نوع گره است. • ]Info/Dlink نشان دهنده داده یا اشاره گر به یک زیر لیست دیگر می باشد. • Link دارای مقدار Null و یا به گره بعدی اشاره می کند. • عموما لیست های عمومی برای نمایش درخت استفاده می شود.
جلسه هفتم لیست پیوندی • انواع گره در لیست عمومی: • در صورتی که Tag برابر با صفر یا False باشد نشان دهنده این است که فیلد وسط (info) دارای ارزش می باشد یعنی فقط داده قرار می گیرد. • در صورتی که Tag برابر با یک یا True باشد نشان دهنده این است که فیلد وسط Dlink دارای آدرس است یعنی فیلد وسط خود اشاره گر است و به یک زیر لیست دیگر اشاره می کند. • لیست عمومی • نمایش فرم پرانتزی لیست عمومی فوق: Glist = (a,(b,c),d,((e)))
جلسه هفتم لیست پیوندی • الگوریتم بازگشتی پیمایش لیست عمومی • پیمایش لیست عمومی void travelsal(Node *Glist) { if ( Glist != Null ) { if (Glist tag ==0) count<< Glist info; else travelsal (Glist Dlink); travelsal (Glist link); } }
جلسه هفتم لیست پیوندی • نمایش چند جمله ای ها با لیست پیوندی • برای نمایش چند جمله ای هر جمله آن را با یک گره لیست پیوندی نمایش می دهیم. هر جمله از یک ضریب و یک توان تشکیل شده است و هر گره طبق ساختاری زیر در لیست پیوندی قرار می گیرد. • Coefficient ضریب • Exponent توان • next اشاره گر با فرض اینکه struct Node { intcoef; int exp ; Node *next; };
جلسه هفتم لیست پیوندی • نمایش چند جمله ای ها با لیست پیوندی • مثال : چند جمله ای زیر را بصورت لیست پیوندی نمایش دهید Null
جلسه هفتم لیست پیوندی • تمرین 1 • پیمایش لیست خطی بصورت غیر بازگشتی : void Display (Node *first) { Node *P = first; while ( P != Null) { count << P info; P = P next; } } • پیمایش لیست خطی بصورت بازگشتیچگونه است ؟
جلسه هفتم لیست پیوندی • تمرین 2 • جستجوی یک مقدار در یک لیست خطی بصورت بازگشتیبصورت : Node * Search (Node *first, elementtype x) { if(first == Null) return Null; else if ( first info == x) return first; else return serach (first next,x); } • جستجوی یک مقدار در لیست خطی بصورت غیر بازگشتی چگونه است ؟
جلسه هفتم لیست پیوندی • تمرین 3 • الگوریتم افزودن عنصر در انتهای لیست پیوندی خطی را بنویسید. • الگوریتم الحاق دو لیست پیوندی را بنویسید. • الگوریتم محاسبه مجموع عناصر لیست پیوندیی صحیح را بنویسید. • الگوریتم محاسبه تعداد عناصر لیست پیوندی را بنویسید. • تمرین 4 • دو ماتریس اسپارس A و B را درنظر بگیرید، تابعی بنویسید که دو ماتریس را به وسیله لیست های پیوندی پیاده سازی نماید. • تمرین 5 • تابعی بنویسید که دو لیست حلقوی را به هم الحاق کند.
Any Question ????