"

ساختار لیست داده پیوندی در جاوا,ساختار لیست داده پیوندی (Linked List) در جاوا چیست؟,اجزای اصلی یک LinkedList

ساختار لیست داده پیوندی در جاوا

ساختار لیست داده پیوندی در جاوا یعنی داده در گره‌های جداگانه ذخیره و هر گره با اشاره‌گر به گره بعدی متصل میشود.درج و حذف سریع

تیم تحریریه
3
0
19 اردیبهشت 1405
لینک کوتاه

ساختار لیست داده پیوندی (Linked List) در جاوا چیست؟

LinkedList در جاوا یک ساختار داده خطی است که عناصر را به صورت گره‌های (Node) جداگانه در حافظه ذخیره می‌کند.
هر گره شامل دو بخش است:
داده (Data) و اشاره‌گر (Pointer) به گره بعدی.
برخلاف آرایه که عناصر به صورت پشت سر هم و در مکان‌های ممتد حافظه ذخیره می‌شوند، در LinkedList گره‌ها می‌توانند در مکان‌های پراکنده حافظه قرار گیرند و با اشاره‌گرها به هم متصل شوند.
 
LinkedList در جاوا بخشی از کالکشن فریمورک (Collection Framework) است و اینترفیس‌های List، Queue و Deque را پیاده‌سازی می‌کند.



ساختار لیست داده پیوندی (Linked List) در جاوا چیست؟
 

تصویر ذهنی یک LinkedList ساده

 
[داده | اشاره‌گر] -> [داده | اشاره‌گر] -> [داده | اشاره‌گر] -> null
هر مستطیل یک گره است. گره اول سر (Head) و گره آخر دم (Tail) نام دارد. اشاره‌گر گره آخر به null ختم می‌شود.
 
مثال ساده:
 
import java.util.LinkedList;


public class LinkedListExample {
    public static void main(String[] args) {
        LinkedList<String> names = new LinkedList<>();
        
        names.add("علی");
        names.add("رضا");
        names.add("سارا");
        
        System.out.println(names);
        // خروجی: [علی, رضا, سارا]
    }
}

ساختار لیست پیوندی در جاوا چگونه است؟

برای درک بهتر ساختار LinkedList، بیایید نگاهی به داخل این کلاس بیندازیم.
 

گره (Node) در LinkedList

هر گره در LinkedList در جاوا از سه بخش تشکیل شده است (در پیاده‌سازی دوطرفه - Doubly Linked List):
// نمای ساده شده از ساختار داخلی LinkedList
class Node<E> {
    E item;        // داده
    Node<E> next;  // اشاره‌گر به گره بعدی
    Node<E> prev;  // اشاره‌گر به گره قبلی (در LinkedList دوطرفه)
}
 
 
نکته مهم: LinkedList در جاوا یک لیست پیوندی دوطرفه (Doubly Linked List) است.
یعنی هر گره هم به گره بعدی (next) و هم به گره قبلی (prev) اشاره می‌کند.
این ویژگی باعث می‌شود پیمایش در هر دو جهت (از اول به آخر و از آخر به اول) به راحتی انجام شود.





🚀 از صفر تا قهرمان جاوا، فقط با یک دوره!
به دنبال یه فرصت طلایی برای شروع برنامه‌نویسی می‌گردی؟
دوره آموزشی جاوا ما، همون چیزیه که نیاز داری!

✨ چرا این دوره رو انتخاب می‌کنی؟
🎯 از مبتدی تا حرفه‌ای
بدون پیش‌زمینه شروع می‌کنی و به یه برنامه‌نویس جاوا تبدیل می‌شی که بازار کار منتظرته!

🛠 پروژه‌محور و عملی
با انجام پروژه‌های واقعی، کدنویسی رو یاد می‌گیری، نه فقط تئوری!

👨‍🏫 پشتیبانی همیشگی
هرجا گیر کنی، تیم پشتیبانی کنارته تا مشکلت حل بشه.

🔓 دسترسی مادام‌العمر
هر وقت خواستی به محتوا دسترسی داری، برای همیشه!

 

🔥 همین حالا ثبت‌نام کن 






اجزای اصلی یک LinkedList

جزء  توضیح
First (Head) اشاره‌گر به اولین گره لیست
Last (Tail)  اشاره‌گر به آخرین گره لیست
Node  هر گره شامل داده، اشاره‌گر به گره بعدی و اشاره‌گر به گره قبلی
Size  تعداد کل گره‌های موجود در لیست
 

نحوه کار LinkedList در جاوا

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

۱. اضافه کردن عنصر (add)

import java.util.LinkedList;


public class AddExample {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        
        // اضافه کردن به انتهای لیست
        list.add("اول");
        list.add("دوم");
        list.add("سوم");
        
        // اضافه کردن به ابتدای لیست
        list.addFirst("صفر");
        
        // اضافه کردن به اندیس مشخص
        list.add(2, "یک و نیم");
        
        System.out.println(list);
        // خروجی: [صفر, اول, یک و نیم, دوم, سوم]
    }
}

نحوه کار add در پس‌زمینه

  • وقتی عنصری به انتها اضافه می‌شود، یک گره جدید ایجاد می‌شود
  • اشاره‌گر next گره آخر قبلی به گره جدید متصل می‌شود
  • اشاره‌گر prev گره جدید به گره آخر قبلی متصل می‌شود
  • متغیر last به گره جدید اشاره می‌کند
 

۲. حذف کردن عنصر (remove)

 
import java.util.LinkedList;


public class RemoveExample {
    public static void main(String[] args) {
        LinkedList<String> list = new LinkedList<>();
        list.add("آبی");
        list.add("قرمز");
        list.add("سبز");
        list.add("زرد");
        
        // حذف از ابتدا
        list.removeFirst();
        
        // حذف از انتها
        list.removeLast();
        
        // حذف با اندیس
        list.remove(0);
        
        System.out.println(list);
        // خروجی: [سبز]
    }
}

نحوه کار remove در پس‌زمینه

  • برای حذف یک گره، اشاره‌گر گره قبلی به گره بعدی متصل می‌شود
  • اشاره‌گر گره بعدی به گره قبلی متصل می‌شود
  • گره مورد نظر از حافظه آزاد می‌شود (Garbage Collection)
 

۳. دسترسی به عناصر (get)

 
import java.util.LinkedList;


public class GetExample {
    public static void main(String[] args) {
        LinkedList<Integer> numbers = new LinkedList<>();
        numbers.add(100);
        numbers.add(200);
        numbers.add(300);
        numbers.add(400);
        
        // دسترسی به عنصر اول
        System.out.println("اولین: " + numbers.getFirst());
        
        // دسترسی به عنصر آخر
        System.out.println("آخرین: " + numbers.getLast());
        
        // دسترسی با اندیس (از 0 شروع می‌شود)
        System.out.println("اندیس 2: " + numbers.get(2));
    }
}

نکته مهم: دسترسی با اندیس در LinkedList کند است. زیرا باید از ابتدا یا انتها شروع به پیمایش کرد تا به اندیس مورد نظر رسید. زمان این عملیات O(n) است.
 

۴. پیمایش LinkedList

import java.util.LinkedList;


public class IterateExample {
    public static void main(String[] args) {
        LinkedList<String> colors = new LinkedList<>();
        colors.add("قرمز");
        colors.add("آبی");
        colors.add("سبز");
        colors.add("زرد");
        
        // روش اول: حلقه for معمولی
        System.out.println("روش اول:");
        for (int i = 0; i < colors.size(); i++) {
            System.out.println(colors.get(i));
        }
        
        // روش دوم: حلقه foreach (توصیه می‌شود)
        System.out.println("\nروش دوم:");
        for (String color : colors) {
            System.out.println(color);
        }
        
        // روش سوم: استفاده از Iterator
        System.out.println("\nروش سوم:");
        java.util.Iterator<String> it = colors.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }
}





نحوه کار LinkedList در جاوا

عملیات ویژه LinkedList (به عنوان Queue و Deque)

LinkedList در جاوا علاوه بر عملیات List، عملیات Queue و Deque را نیز پشتیبانی می‌کند.
 

استفاده به عنوان Queue (صف - FIFO)

import java.util.LinkedList;
import java.util.Queue;


public class QueueExample {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();
        
        // افزودن به انتهای صف
        queue.add("اولین");
        queue.add("دومین");
        queue.add("سومین");
        
        // مشاهده عنصر اول بدون حذف
        System.out.println("سر صف: " + queue.peek());
        
        // حذف و برگرداندن عنصر اول
        System.out.println("خارج شده: " + queue.poll());
        System.out.println("خارج شده: " + queue.poll());
        
        System.out.println("باقیمانده: " + queue);
    }
}

استفاده به عنوان Deque (دک - دوطرفه)

import java.util.Deque;
import java.util.LinkedList;


public class DequeExample {
    public static void main(String[] args) {
        Deque<String> deque = new LinkedList<>();
        
        // افزودن از دو طرف
        deque.addFirst("اول");
        deque.addLast("آخر");
        deque.addFirst("جديدترين اول");
        deque.addLast("جديدترين آخر");
        
        System.out.println("Deque: " + deque);
        
        // گرفتن از دو طرف
        System.out.println("گرفته شده از اول: " + deque.removeFirst());
        System.out.println("گرفته شده از آخر: " + deque.removeLast());
        
        System.out.println("بعد از عملیات: " + deque);
    }
}

مزایا و معایب LinkedList در جاوا

مزایا

  • درج و حذف

    در ابتدا و میانه با سرعت بالا زمان O(1) برای درج/حذف در ابتدا و انتها، اگر اشاره‌گر به گره مورد نظر داشته باشید
  • استفاده بهینه از حافظه

    حافظه به صورت پویا تخصیص داده می‌شود و فقط به اندازه نیاز مصرف می‌کند
  • عدم نیاز به حافظه ممتد

    گره‌ها می‌توانند در هر جای حافظه پراکنده باشند
  • انعطاف بالا

    می‌تواند به عنوان List، Queue و Deque استفاده شود
  • پیمایش دوطرفه

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

معایب

  • دسترسی تصادفی کند

    برای دسترسی به عنصر با اندیس مشخص، باید پیمایش کرد. زمان O(n)
  • حافظه اضافی مصرف می‌کند

    هر گره علاوه بر داده، دو اشاره‌گر (next و prev) هم ذخیره می‌کند
  • پیمایش خطی کند

    برخلاف آرایه که عناصر پشت سر هم هستند، در LinkedList پیمایش ممکن است کش (Cache) را به خوبی استفاده نکند
  • پیچیدگی بیشتر

    نسبت به ArrayList، کدنویسی و مدیریت پیچیده‌تری دارد



مزایا و معایب LinkedList در جاوا



تفاوت ArrayList و LinkedList در جاوا

این یکی از مهم‌ترین مقایسه‌ها در برنامه‌نویسی جاوا است. انتخاب درست بین این دو تأثیر زیادی بر کارایی برنامه دارد.

ویژگی   LinkedList ArrayList
ساختار داخلی  آرایه پویا (داینامیک)  لیست پیوندی دوطرفه
دسترسی با اندیس (get)  خیلی سریع O(1)  کند O(n)
درج/حذف در ابتدا  کند O(n) - جابه‌جایی همه عناصر  سریع O(1)
درج/حذف در انتها  سریع O(1) (با احتساب افزایش ظرفیت)  سریع O(1)
درج/حذف در میانه  کند O(n) - جابه‌جایی عناصر  نسبتاً سریع O(n) (پیمایش + درج ثابت)
مصرف حافظه  کمتر (فقط داده + یک متغیر size)  بیشتر (داده + دو اشاره‌گر)
پیمایش با حلقه  سریع (کش فریندلی)  نسبتاً کند
مناسب برای خواندن مکرر، دسترسی تصادفی درج و حذف مکرر در ابتدا و میانه



مثال مقایسه عملی

import java.util.*;


public class CompareExample {
    public static void main(String[] args) {
        // تست ArrayList
        List<Integer> arrayList = new ArrayList<>();
        // تست LinkedList
        List<Integer> linkedList = new LinkedList<>();
        
        // درج در ابتدا - LinkedList برنده است
        long start = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            arrayList.add(0, i);  // کند
        }
        long end = System.nanoTime();
        System.out.println("ArrayList add first: " + (end - start) + " ns");
        
        start = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            linkedList.add(0, i);  // سریع
        }
        end = System.nanoTime();
        System.out.println("LinkedList add first: " + (end - start) + " ns");
        
        // دسترسی تصادفی - ArrayList برنده است
        start = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            arrayList.get(5000);
        }
        end = System.nanoTime();
        System.out.println("ArrayList get: " + (end - start) + " ns");
        
        start = System.nanoTime();
        for (int i = 0; i < 10000; i++) {
            linkedList.get(5000);  // کند
        }
        end = System.nanoTime();
        System.out.println("LinkedList get: " + (end - start) + " ns");
    }
}




چه زمانی از LinkedList استفاده کنیم؟

✅ از LinkedList استفاده کنید اگر:

  • عملیات درج و حذف در ابتدای لیست زیاد دارید (مثل صف یا استک)
  • دسترسی تصادفی با اندیس کم اهمیت است
  • لیست شما مدام در حال تغییر است (اضافه و حذف مکرر)
  • می‌خواهید از قابلیت‌های Queue یا Deque استفاده کنید
  • اندازه لیست از قبل مشخص نیست و مدام تغییر می‌کند
 

❌ از LinkedList استفاده نکنید اگر:

  • دسترسی تصادفی و پرش مکرر به عناصر با اندیس دارید (به جای آن از ArrayList استفاده کنید)
  • حجم لیست بسیار زیاد است و حافظه محدود (ArrayList مصرف حافظه کمتری دارد)
  • بیشتر عملیات شما خواندن (get) است تا نوشتن
 

مثال کامل و کاربردی: سیستم مدیریت صف مشتریان

import java.util.LinkedList;
import java.util.Queue;


class Customer {
    String name;
    String service;
    
    Customer(String name, String service) {
        this.name = name;
        this.service = service;
    }
    
    @Override
    public String toString() {
        return name + " (" + service + ")";
    }
}


public class CustomerQueueSystem {
    public static void main(String[] args) {
        Queue<Customer> queue = new LinkedList<>();
        
        // مشتریان وارد صف می‌شوند
        queue.add(new Customer("علی رضایی", "افتتاح حساب"));
        queue.add(new Customer("سارا محمدی", "دریافت کارت"));
        queue.add(new Customer("رضا کریمی", "مشاوره سرمایه‌گذاری"));
        queue.add(new Customer("مریم احمدی", "تغییر رمز"));
        
        System.out.println("صف مشتریان: " + queue.size() + " نفر");
        
        // خدمت رسانی به مشتریان
        int number = 1;
        while (!queue.isEmpty()) {
            Customer current = queue.poll();
            System.out.println(number + ". خدمت به " + current);
            number++;
        }
        
        System.out.println("همه مشتریان خدمت دریافت کردند.");
    }
}

جمع‌بندی

LinkedList در جاوا یک ساختار داده قدرتمند و انعطاف‌پذیر است که برای سناریوهای خاصی بسیار مناسب است.
نکاتی که باید به خاطر بسپارید:
  • ساختار: لیست پیوندی دوطرفه که هر گره به گره بعدی و قبلی اشاره می‌کند.
  • نقاط قوت: درج و حذف سریع در ابتدا و انتها (O(1))، مصرف حافظه پویا، قابلیت استفاده به عنوان Queue و Deque.
  • نقاط ضعف: دسترسی تصادفی کند (O(n))، مصرف حافظه اضافی برای اشاره‌گرها.
  • مقایسه با ArrayList: اگر نیاز به درج/حذف مکرر دارید → LinkedList؛ اگر نیاز به خواندن و دسترسی تصادفی دارید → ArrayList.
  • کاربردها: صف‌ها، تاریخچه مرورگر، مدیریت حافظه، پیاده‌سازی پشته و صف‌های اولویت‌دار.
انتخاب بین ArrayList و LinkedList باید بر اساس نیاز واقعی برنامه شما انجام شود. هیچکدام ذاتاً بهتر از دیگری نیست؛ هر کدام برای کاربرد خاص خود طراحی شده است.
 

محصولات مرتبط

کاربران ما

شما هم نظرتون با ما دریاره “ساختار لیست داده پیوندی در جاوا” اشتراک بزارید

برای ارسال نظر لطفا ورود یا ثبت نام کنید

منو