المپدیا

دانش‌نامه‌ی المپیاد کامپیوتر ایران

ابزار کاربر

ابزار سایت


آموزش:الگوریتم:آرایه و لیست

آرایه و لیست

تعریف

آرایه

آرایه مجموعه‌ای از ثابت‌ها یا متغیرهاست که از ویژگی‌های زیر برخوردارند:

  • از یک نوع داده هستند.
  • پشت هم در حافظه ذخیره می‌شوند.
  • تحت یک نام مشترک استفاده می‌شوند.

شاخص‌ها و بُعد آرایه

آرایه یک داده‌ساختار شاخص‌بندی شده است؛ یعنی هر عنصر با یک یا چند اندیس معین می‌گردد. توجه کنید که اندیس‌ها ممکن است خود یک متغیر باشند و در زمان اجرا تعیین شوند. با این حال، خواندن و نوشتن هر یک از عناصر آرایه در زمان ثابت انجام می‌شوند. به تعداد اندیس‌هایی که برای نشان دادن یک عنصر استفاده می کنیم، بعد آرایه می‌گوییم.

آرایه‌ها معمولاً اندازه‌ی ثابتی دارند و در بعضی پیاده‌سازی‌ها، اندازه‌ی آرایه‌ها باید در زمان کامپایل مشخص باشد. انواع پیچیده‌تری از داده‌ساختارها مثل آرایه‌های پویا، از این قابلیت برخوردارند که اندازه‌ی خود را در زمان اجرا به قدر نیاز بزرگ کنند.

اگر اندازه‌ی آرایه $n$ باشد، هر اندیس معتبر و قابل استفاده باید عددی بین ۰ تا $n-1$ باشد (در آرایه های چند بعدی هم، هر یک از اندیس‌ها باید بین ۰ تا یکی کم‌تر از اندازه‌ی بعد باشد). استفاده از اندیسی خارج از این بازه ممکن است منجر به خطای زمان اجرا یا رفتارهای نامشخص برنامه شود. این یکی از رایج‌ترین خطاهای برنامه‌نویسان است؛ معمولاً طول آرایه را کمی بیشتر از نیاز واقعی می گیریم، تا از خطاهای غیر ضروری پرهیز کرده باشیم.

نحوه‌ی استفاده

دستور زیر، آرایه‌ای به طول ۵ تعریف کرده و مقادیر اولیه‌ای به آن می‌دهد.

int a[5] = {2, -1, 14, 0, 2};

دستور زیر، به خانه‌ی دوم آرایه مقدار جدیدی می دهد. توجه کنید که اندیس‌ها از ۰ شروع می‌شوند!

a[1] = a[0] + 5; // a[1] is now 7

لیست پیوندی

لیست پیوندی مجموعه‌ای از گره‌هاست که یک دنباله تشکیل می‌دهند. در ساده‌ترین حالت، هر گره از یک داده و یک اشاره‌گر به گره‌ی بعد تشکیل شده است؛ امّا می‌تواند پیچیدگی‌های بیشتری داشته باشد. مثلاً ممکن است هر عنصر، به عنصر قبلی خود هم پیوند داشته باشد (لیست دو-سویه)، یا عنصر آخر به عنصر اول پیوند داشته باشد (لیست دوری).

مقایسه‌ی لیست با آرایه

تفاوت اصلی یک لیست با آرایه این است که ترتیب قرار گرفتن عناصر در آن، با ترتیب قرار گرفتن عناصر در حافظه متفاوت است. لذا حذف یا درج یک عنصر به بازآرایی تمام عناصر در حافظه نیاز ندارد. به همین خاطر عملیات حذف و درج در لیست‌ها به سادگی و در زمان ثابت انجام می‌شود. در صورتی که در آرایه‌ها، به خاطر حفظ خاصیت پشت‌ هم بودن عناصر در حافظه، مجبور به شیفت دادن بخش زیادی از داده‌ها هستیم.

از طرف دیگر لیست پیوندی اجازه‌ی دسترسی تصادفی به عناصر خود یا اندیس‌گذاری را نمی‌دهد. لذا بسیاری از عملیات اولیه نظیر یافتن اندیس مورد نظر، ممکن است نیازمند بررسی بیشتر عناصر لیست باشد.

لیست یک داده‌ساختار پویاست. به این معنی که در هر لحظه از زمان اجرا، حافظه‌ی مورد نیازش را می گیرد.

به علت وجود اشاره‌گرهای فراوان، لیست پیوندی از حافظه‌ی بیشتری استفاده می کند.

عناصر لیست پیوندی پشت هم در حافظه ذخیره نمی‌شوند. این باعث می شود دسترسی به تک‌تک عناصر یا پردازش جمعی اطلاعات (مثل مقداردهی اولیه) کندتر باشد.

لیست‌ها ارتباط تنگاتنگی با اشاره‌گرها دارند که این امر پیچیدگی برنامه و احتمال اشتباه را، به ویژه برای برنامه نویسان تازه‌کار بیش‌تر می‌کند.

کاربردهای لیست

لیست‌های پیوندی به عنوان یکی از داده‌ساختارهای پایه‌ای، کاربرد فراوانی دارد. ساختارهای دیگری مثل صف، پشته، جدول درهم‌سازی، مجموعه‌های مجزا، و … را می‌توان با لیست‌های پیوندی پیاده‌سازی کرد.

یکی از کاربردهای پرتکرار لیست‌های پیوندی، نگه‌داری لیست مجاورت در گراف‌های خلوت (با تعداد یال کم نسبت به رأس‌‌ها) است. اگر اندازه‌ی گراف بزرگ باشد، شاید امکان نگه‌داری ماتریس مجاورت وجود نداشته باشد. در این مواقع می‌توانیم برای هر رأس، همسایگانش را در یک لیست پیوندی ذخیره کنیم.

کاربرد قابل لمس لیست‌های پیوندی در ویرایش‌گرهای متنی است که نیازمند داده ساختاری هستیم که نسبت به درج و حذف‌های متوالی کارآمد باشد.

پیاده‌سازی

لیست‌های پیوندی را به روش‌های مختلفی می‌توان پیاده‌سازی کرد. کتاب‌خانه‌ی <list> در ++C یک پیاده‌سازی استاندارد برای لیست‌های پیوندیست.

برخی برای پیاده‌سازی یک لیست، از یک آرایه‌ی کمکی استفاده می‌کنند و بدین ترتیب در هر گره، به جای یک اشاره‌گر به گره‌ی بعدی، یک اندیس نگه‌داری می‌کنند.


ابزار صفحه