📜  C中双向链表上所有操作的菜单驱动程序(1)

📅  最后修改于: 2023-12-03 14:40:25.059000             🧑  作者: Mango

C中双向链表上所有操作的菜单驱动程序

这是一个基于C语言的双向链表操作的菜单驱动程序,具有插入、删除、查找、打印等基本操作。

简介

双向链表是常用的一种数据结构,它由多个节点组成,每个节点包含一个数据域和两个指针域,指向前一个节点和后一个节点。相比于单向链表,双向链表可以实现更灵活的操作。

本程序实现了基本的双向链表操作,包括:

  • 在头部插入节点
  • 在尾部插入节点
  • 在指定位置插入节点
  • 删除指定位置节点
  • 查找指定节点
  • 打印所有节点
代码片段

以下是本程序的核心代码片段,详细的注释可以帮助理解每个函数的功能。

//节点结构体
typedef struct Node {
    int data;
    struct Node* prev;
    struct Node* next;
} Node;

//在头部插入节点
Node* insertAtHead(Node* head, int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->prev = NULL;
    newNode->next = head;
    if (head != NULL) {
        head->prev = newNode;
    }
    head = newNode;
    
    return head;
}

//在尾部插入节点
Node* insertAtTail(Node* head, int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->prev = NULL;
    newNode->next = NULL;
    if (head == NULL) {
        head = newNode;
    } else {
        Node* current = head;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = newNode;
        newNode->prev = current;
    }

    return head;
}

//在指定位置插入节点
Node* insertAtPosition(Node* head, int data, int position) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->prev = NULL;
    newNode->next = NULL;
    if (position == 1) { //在头部插入
        head = insertAtHead(head, data);
    } else {
        Node* current = head;
        int i;
        for (i = 1; i < position-1 && current != NULL; i++) {
            current = current->next;
        }
        if (current != NULL) {
            newNode->prev = current;
            newNode->next = current->next;
            if (current->next != NULL) {
                current->next->prev = newNode;
            }
            current->next = newNode;
        } else {
            printf("Error: invalid position.\n");
        }
    }

    return head;
}

//删除指定位置节点
Node* deleteAtPosition(Node* head, int position) {
    if (head == NULL) {
        printf("Error: empty list.\n");
        return head;
    }
    if (position == 1) { //删除头部节点
        Node* current = head->next;
        free(head);
        head = current;
        if (head != NULL) {
            head->prev = NULL;
        }
    } else {
        Node* current = head;
        int i;
        for (i = 1; i < position && current != NULL; i++) {
            current = current->next;
        }
        if (current != NULL) {
            if (current->prev != NULL) {
                current->prev->next = current->next;
            }
            if (current->next != NULL) {
                current->next->prev = current->prev;
            }
            free(current);
        } else {
            printf("Error: invalid position.\n");
        }
    }

    return head;
}

//查找指定节点
Node* search(Node* head, int key) {
    Node* current = head;
    while (current != NULL) {
        if (current->data == key) {
            printf("Node with data %d found.\n", key);
            return current;
        }
        current = current->next;
    }
    printf("Node with data %d not found.\n", key);
    return NULL;
}

//打印所有节点
void printList(Node* head) {
    Node* current = head;
    printf("List: ");
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}
使用示例

以下是本程序的使用示例,可以根据需要进行修改并编译运行。

#include <stdio.h>
#include <stdlib.h>

//节点结构体
typedef struct Node {
    int data;
    struct Node* prev;
    struct Node* next;
} Node;

//在头部插入节点
Node* insertAtHead(Node* head, int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->prev = NULL;
    newNode->next = head;
    if (head != NULL) {
        head->prev = newNode;
    }
    head = newNode;
    
    return head;
}

//在尾部插入节点
Node* insertAtTail(Node* head, int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->prev = NULL;
    newNode->next = NULL;
    if (head == NULL) {
        head = newNode;
    } else {
        Node* current = head;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = newNode;
        newNode->prev = current;
    }

    return head;
}

//在指定位置插入节点
Node* insertAtPosition(Node* head, int data, int position) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    newNode->data = data;
    newNode->prev = NULL;
    newNode->next = NULL;
    if (position == 1) { //在头部插入
        head = insertAtHead(head, data);
    } else {
        Node* current = head;
        int i;
        for (i = 1; i < position-1 && current != NULL; i++) {
            current = current->next;
        }
        if (current != NULL) {
            newNode->prev = current;
            newNode->next = current->next;
            if (current->next != NULL) {
                current->next->prev = newNode;
            }
            current->next = newNode;
        } else {
            printf("Error: invalid position.\n");
        }
    }

    return head;
}

//删除指定位置节点
Node* deleteAtPosition(Node* head, int position) {
    if (head == NULL) {
        printf("Error: empty list.\n");
        return head;
    }
    if (position == 1) { //删除头部节点
        Node* current = head->next;
        free(head);
        head = current;
        if (head != NULL) {
            head->prev = NULL;
        }
    } else {
        Node* current = head;
        int i;
        for (i = 1; i < position && current != NULL; i++) {
            current = current->next;
        }
        if (current != NULL) {
            if (current->prev != NULL) {
                current->prev->next = current->next;
            }
            if (current->next != NULL) {
                current->next->prev = current->prev;
            }
            free(current);
        } else {
            printf("Error: invalid position.\n");
        }
    }

    return head;
}

//查找指定节点
Node* search(Node* head, int key) {
    Node* current = head;
    while (current != NULL) {
        if (current->data == key) {
            printf("Node with data %d found.\n", key);
            return current;
        }
        current = current->next;
    }
    printf("Node with data %d not found.\n", key);
    return NULL;
}

//打印所有节点
void printList(Node* head) {
    Node* current = head;
    printf("List: ");
    while (current != NULL) {
        printf("%d ", current->data);
        current = current->next;
    }
    printf("\n");
}

//主函数
int main() {
    Node* head = NULL;
    int choice, value, position;

    do {
        //菜单
        printf("\n\n##### MENU #####\n");
        printf("1. Insert at head\n");
        printf("2. Insert at tail\n");
        printf("3. Insert at position\n");
        printf("4. Delete at position\n");
        printf("5. Search\n");
        printf("6. Print list\n");
        printf("7. Exit\n");
        printf("Enter your choice: ");
        scanf("%d", &choice);

        //根据选择执行相应操作
        switch(choice) {
            case 1:
                printf("Enter value to insert: ");
                scanf("%d", &value);
                head = insertAtHead(head, value);
                break;
            case 2:
                printf("Enter value to insert: ");
                scanf("%d", &value);
                head = insertAtTail(head, value);
                break;
            case 3:
                printf("Enter position: ");
                scanf("%d", &position);
                printf("Enter value to insert: ");
                scanf("%d", &value);
                head = insertAtPosition(head, value, position);
                break;
            case 4:
                printf("Enter position: ");
                scanf("%d", &position);
                head = deleteAtPosition(head, position);
                break;
            case 5:
                printf("Enter value to search: ");
                scanf("%d", &value);
                search(head, value);
                break;
            case 6:
                printList(head);
                break;
            case 7:
                printf("Exiting...\n");
                break;
            default:
                printf("Invalid choice.\n");
        }
    } while(choice != 7);

    return 0;
}
注意事项
  • 在操作链表前,要先为头节点赋值为NULL。
  • 操作链表时,要注意节点指针是否为空。
  • 操作完成后,要释放不再需要的内存。
  • 在编写菜单程序时,要注意用户输入的数据是否合法,避免崩溃。