رفتن به محتوای اصلی
برنامه‌سازی پیشرفته با پایتون درس‌نامهٔ آزاد
درس متوسط ۳۰ دقیقه

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

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

هدف این درس

بتوانی برای هر مسئله ساختار و الگوریتم مناسب را با استدلال پیچیدگی انتخاب کنی.

در این مطلب ۴

این بخش «ساختمان داده» نیست که جای درس ساختمان داده را بگیرد؛ جعبه‌ابزار انتخاب درست در برنامه‌سازی روزمره است: کدام کالکشن، کدام الگوریتم، با چه هزینه‌ای.

چهار کالکشن اصلی

ساختارنگه می‌داردجست‌وجوترتیب
listدنبالهٔ قابل تغییرخطیدارد
tupleدنبالهٔ ثابتخطیدارد
setعضوهای یکتامیانگین ثابتندارد
dictکلید → مقدارمیانگین ثابتترتیب درج
names = ["سارا", "علی", "سارا"]
unique = set(names)              # {'سارا', 'علی'} — حذف تکراری در یک خط
scores = {"سارا": 19, "علی": 17}
print(scores.get("رضا", "ثبت نشده"))  # دسترسی امن با پیش‌فرض

تکرارگر در برابر تکرارپذیر

تکرارپذیر (iterable) چیزی است که می‌شود رویش حلقه زد؛ تکرارگر (iterator) اشاره‌گرِ حالت‌داری است که با next جلو می‌رود و یک‌بارمصرف است.

nums = [1, 2, 3]     # iterable
it = iter(nums)      # iterator
print(next(it))      # 1
print(next(it))      # 2

مولد: دنبالهٔ تنبل

def evens(limit):
    n = 0
    while n < limit:
        yield n
        n += 2

for e in evens(1_000_000_000):
    if e > 10:
        break
    print(e)

مولد هیچ‌وقت کل دنباله را در حافظه نمی‌سازد؛ هر مقدار موقع نیاز تولید می‌شود. برای دادهٔ بزرگ یا جریانی، تفاوت «برنامه‌ای که اجرا می‌شود» و «برنامه‌ای که حافظه تمام می‌کند» همین yield است.

پیچیدگی: زبان مقایسهٔ الگوریتم‌ها

فرمول
رشد درجه‌دوم: با دوبرابرشدن ورودی، زمان تقریباً چهار برابر می‌شود

جزئیات کامل نماد و جدول مقایسه در تعریف O بزرگ و پیچیدگی‌های رایج آمده؛ این‌جا فقط شهود: جست‌وجوی خطی در لیست است، عضویت در set میانگین ، و جست‌وجوی دودویی روی دادهٔ مرتب .

def linear_search(items, target):
    for i, item in enumerate(items):
        if item == target:
            return i
    return -1

def binary_search(items, target):  # items باید مرتب باشد
    lo, hi = 0, len(items) - 1
    while lo <= hi:
        mid = (lo + hi) // 2
        if items[mid] == target:
            return mid
        if items[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1
    return -1
برداشت نادرست رایج

اشتباه رایج

مرتب‌سازی همیشه اول کار لازم است چون جست‌وجوی دودویی سریع‌تر است.

تصحیح

مرتب‌سازی خودش O(n log n) هزینه دارد. اگر فقط چند جست‌وجو داری، جست‌وجوی خطی ارزان‌تر تمام می‌شود. هزینهٔ کل را حساب کن، نه هزینهٔ یک قدم را.

سنجش فهم — کالکشن و پیچیدگی

۰ از ۳ پاسخ داده شده

  1. بررسی عضویت مکرر در مجموعه‌ای با یک میلیون عضو؟
  2. مزیت اصلی مولد (yield) نسبت به برگرداندن لیست چیست؟
  3. در بدترین حالت، جست‌وجوی خطی در لیست ۱۰۰۰ عضوی حداکثر چند مقایسه می‌کند؟ (فقط عدد)(پاسخ عددی)

اول به همهٔ پرسش‌ها پاسخ دهید، بعد بررسی کنید.

مطالب مرتبط

از همین بخش و با برچسب‌های مشترک

این مطلب را خواندید؟ آن را علامت بزنید تا پیشرفت شما روی همین دستگاه ذخیره شود.

وضعیت پیشرفت برای کالکشن‌ها و الگوریتم‌های پایه