ساختار لیست داده پیوندی در جاوا
ساختار لیست داده پیوندی در جاوا یعنی داده در گرههای جداگانه ذخیره و هر گره با اشارهگر به گره بعدی متصل میشود.درج و حذف سریع
19 اردیبهشت 1405
لینک کوتاه
ساختار لیست داده پیوندی (Linked List) در جاوا چیست؟
LinkedList در جاوا یک ساختار داده خطی است که عناصر را به صورت گرههای (Node) جداگانه در حافظه ذخیره میکند.
هر گره شامل دو بخش است:
داده (Data) و اشارهگر (Pointer) به گره بعدی.
برخلاف آرایه که عناصر به صورت پشت سر هم و در مکانهای ممتد حافظه ذخیره میشوند، در LinkedList گرهها میتوانند در مکانهای پراکنده حافظه قرار گیرند و با اشارهگرها به هم متصل شوند.
هر گره شامل دو بخش است:
داده (Data) و اشارهگر (Pointer) به گره بعدی.
برخلاف آرایه که عناصر به صورت پشت سر هم و در مکانهای ممتد حافظه ذخیره میشوند، در LinkedList گرهها میتوانند در مکانهای پراکنده حافظه قرار گیرند و با اشارهگرها به هم متصل شوند.
LinkedList در جاوا بخشی از کالکشن فریمورک (Collection Framework) است و اینترفیسهای List، Queue و Deque را پیادهسازی میکند.
-in-Java.jpg)
-in-Java.jpg)
تصویر ذهنی یک 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) اشاره میکند.
این ویژگی باعث میشود پیمایش در هر دو جهت (از اول به آخر و از آخر به اول) به راحتی انجام شود.
یعنی هر گره هم به گره بعدی (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 (به عنوان 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، کدنویسی و مدیریت پیچیدهتری دارد

تفاوت 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 باید بر اساس نیاز واقعی برنامه شما انجام شود. هیچکدام ذاتاً بهتر از دیگری نیست؛ هر کدام برای کاربرد خاص خود طراحی شده است.

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