雙向鏈表(Doubly Linked List)是一種常見的數據結構,它由一系列節點組成,每個節點包含兩個指針:一個指向前一個節點(prev
),另一個指向下一個節點(next
)。與單向鏈表不同,雙向鏈表可以從任意一個節點向前或向后遍歷整個鏈表。
雙向鏈表的主要特點包括: - 雙向遍歷:可以從頭到尾或從尾到頭遍歷鏈表。 - 插入和刪除操作高效:由于每個節點都保存了前驅和后繼節點的信息,插入和刪除操作的時間復雜度為 O(1)。 - 占用更多內存:每個節點需要額外的指針來存儲前驅節點的地址,因此比單向鏈表占用更多的內存。
在C語言中,雙向鏈表的節點通常定義為一個結構體,包含數據域和兩個指針域:
struct Node {
int data; // 數據域
struct Node* prev; // 指向前一個節點的指針
struct Node* next; // 指向下一個節點的指針
};
首先,我們需要一個函數來創建新的節點:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* prev;
struct Node* next;
};
struct Node* createNode(int data) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if (newNode == NULL) {
printf("Memory allocation failed\n");
exit(1);
}
newNode->data = data;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
void insertAtHead(struct Node** head, int data) {
struct Node* newNode = createNode(data);
if (*head == NULL) {
*head = newNode;
} else {
newNode->next = *head;
(*head)->prev = newNode;
*head = newNode;
}
}
void insertAtTail(struct Node** head, int data) {
struct Node* newNode = createNode(data);
if (*head == NULL) {
*head = newNode;
} else {
struct Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
newNode->prev = temp;
}
}
void insertAtPosition(struct Node** head, int data, int position) {
if (position < 1) {
printf("Invalid position\n");
return;
}
if (position == 1) {
insertAtHead(head, data);
return;
}
struct Node* newNode = createNode(data);
struct Node* temp = *head;
for (int i = 1; i < position - 1 && temp != NULL; i++) {
temp = temp->next;
}
if (temp == NULL) {
printf("Position out of range\n");
return;
}
newNode->next = temp->next;
if (temp->next != NULL) {
temp->next->prev = newNode;
}
temp->next = newNode;
newNode->prev = temp;
}
void deleteAtHead(struct Node** head) {
if (*head == NULL) {
printf("List is empty\n");
return;
}
struct Node* temp = *head;
*head = (*head)->next;
if (*head != NULL) {
(*head)->prev = NULL;
}
free(temp);
}
void deleteAtTail(struct Node** head) {
if (*head == NULL) {
printf("List is empty\n");
return;
}
struct Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
if (temp->prev != NULL) {
temp->prev->next = NULL;
} else {
*head = NULL;
}
free(temp);
}
void deleteAtPosition(struct Node** head, int position) {
if (*head == NULL || position < 1) {
printf("List is empty or invalid position\n");
return;
}
struct Node* temp = *head;
if (position == 1) {
deleteAtHead(head);
return;
}
for (int i = 1; i < position && temp != NULL; i++) {
temp = temp->next;
}
if (temp == NULL) {
printf("Position out of range\n");
return;
}
if (temp->next != NULL) {
temp->next->prev = temp->prev;
}
if (temp->prev != NULL) {
temp->prev->next = temp->next;
}
free(temp);
}
void printListForward(struct Node* head) {
struct Node* temp = head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
void printListBackward(struct Node* head) {
struct Node* temp = head;
if (temp == NULL) {
printf("List is empty\n");
return;
}
while (temp->next != NULL) {
temp = temp->next;
}
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->prev;
}
printf("NULL\n");
}
為了避免內存泄漏,我們需要在程序結束時釋放鏈表占用的內存:
void freeList(struct Node** head) {
struct Node* temp;
while (*head != NULL) {
temp = *head;
*head = (*head)->next;
free(temp);
}
}
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* prev;
struct Node* next;
};
struct Node* createNode(int data) {
struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
if (newNode == NULL) {
printf("Memory allocation failed\n");
exit(1);
}
newNode->data = data;
newNode->prev = NULL;
newNode->next = NULL;
return newNode;
}
void insertAtHead(struct Node** head, int data) {
struct Node* newNode = createNode(data);
if (*head == NULL) {
*head = newNode;
} else {
newNode->next = *head;
(*head)->prev = newNode;
*head = newNode;
}
}
void insertAtTail(struct Node** head, int data) {
struct Node* newNode = createNode(data);
if (*head == NULL) {
*head = newNode;
} else {
struct Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
newNode->prev = temp;
}
}
void insertAtPosition(struct Node** head, int data, int position) {
if (position < 1) {
printf("Invalid position\n");
return;
}
if (position == 1) {
insertAtHead(head, data);
return;
}
struct Node* newNode = createNode(data);
struct Node* temp = *head;
for (int i = 1; i < position - 1 && temp != NULL; i++) {
temp = temp->next;
}
if (temp == NULL) {
printf("Position out of range\n");
return;
}
newNode->next = temp->next;
if (temp->next != NULL) {
temp->next->prev = newNode;
}
temp->next = newNode;
newNode->prev = temp;
}
void deleteAtHead(struct Node** head) {
if (*head == NULL) {
printf("List is empty\n");
return;
}
struct Node* temp = *head;
*head = (*head)->next;
if (*head != NULL) {
(*head)->prev = NULL;
}
free(temp);
}
void deleteAtTail(struct Node** head) {
if (*head == NULL) {
printf("List is empty\n");
return;
}
struct Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
if (temp->prev != NULL) {
temp->prev->next = NULL;
} else {
*head = NULL;
}
free(temp);
}
void deleteAtPosition(struct Node** head, int position) {
if (*head == NULL || position < 1) {
printf("List is empty or invalid position\n");
return;
}
struct Node* temp = *head;
if (position == 1) {
deleteAtHead(head);
return;
}
for (int i = 1; i < position && temp != NULL; i++) {
temp = temp->next;
}
if (temp == NULL) {
printf("Position out of range\n");
return;
}
if (temp->next != NULL) {
temp->next->prev = temp->prev;
}
if (temp->prev != NULL) {
temp->prev->next = temp->next;
}
free(temp);
}
void printListForward(struct Node* head) {
struct Node* temp = head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL\n");
}
void printListBackward(struct Node* head) {
struct Node* temp = head;
if (temp == NULL) {
printf("List is empty\n");
return;
}
while (temp->next != NULL) {
temp = temp->next;
}
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->prev;
}
printf("NULL\n");
}
void freeList(struct Node** head) {
struct Node* temp;
while (*head != NULL) {
temp = *head;
*head = (*head)->next;
free(temp);
}
}
int main() {
struct Node* head = NULL;
insertAtHead(&head, 10);
insertAtHead(&head, 20);
insertAtTail(&head, 30);
insertAtPosition(&head, 40, 2);
printf("Forward traversal: ");
printListForward(head);
printf("Backward traversal: ");
printListBackward(head);
deleteAtHead(&head);
deleteAtTail(&head);
deleteAtPosition(&head, 2);
printf("Forward traversal after deletion: ");
printListForward(head);
freeList(&head);
return 0;
}
雙向鏈表是一種功能強大的數據結構,它允許我們在鏈表中進行雙向遍歷,并且在插入和刪除操作時具有較高的效率。通過本文的介紹和示例代碼,你應該已經掌握了如何在C語言中實現雙向鏈表的基本操作。希望這篇文章對你理解和使用雙向鏈表有所幫助!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。