📜  菜单驱动程序实现双循环链表的所有操作(1)

📅  最后修改于: 2023-12-03 15:41:31.584000             🧑  作者: Mango

双循环链表操作菜单驱动程序

本文介绍了如何使用菜单驱动程序来实现双循环链表的所有操作。

双循环链表简介

双循环链表是一种链式存储结构,它由若干个结点组成,每个结点包含两个指针域,一个指向前驱结点,一个指向后继结点。它的最后一个结点的后继指针指向头结点,头结点的前驱指针指向最后一个结点,因此形成一个双向循环链表。

菜单驱动程序简介

菜单驱动程序是一种交互式程序设计技术,它通过显示一个菜单列表让用户选择操作,然后执行用户选择的操作。菜单驱动程序可以被用来实现任何需要用户选择操作的程序,包括双循环链表操作。

双循环链表操作菜单列表

以下是我们将要实现的双循环链表操作菜单列表:

== 双循环链表操作菜单 ==
1. 创建双循环链表
2. 插入结点
3. 删除结点
4. 查找结点
5. 显示双循环链表
6. 退出程序

该菜单列表包含了以下操作:

  1. 创建双循环链表。
  2. 插入结点。
  3. 删除结点。
  4. 查找结点。
  5. 显示双循环链表。
  6. 退出程序。

我们将分别实现这些操作。

创建双循环链表

用户可以在菜单列表中选择创建双循环链表操作。该操作将创建一个空的双循环链表。

以下是创建双循环链表的代码片段:

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

typedef struct Node {
    int data;
    struct Node* prev;
    struct Node* next;
} Node;

Node* createDLList() {
    Node* head = (Node*) malloc(sizeof(Node));
    head->prev = head;
    head->next = head;
    return head;
}

int main() {
    Node* head = createDLList();
    // ...
    return 0;
}

该函数返回一个指针,指向创建的双循环链表的头结点。

插入结点

用户可以在菜单列表中选择插入结点操作。该操作将在指定位置插入一个新结点。

以下是插入结点的代码片段:

void insert(Node* head, int pos, int data) {
    if (pos < 0) {
        printf("Invalid position!\n");
        return;
    }
    Node* p = head;
    for (int i = 0; i < pos; i++) {
        p = p->next;
        if (p == head) {
            printf("Out of range!\n");
            return;
        }
    }
    Node* q = (Node*) malloc(sizeof(Node));
    q->data = data;
    q->prev = p;
    q->next = p->next;
    p->next->prev = q;
    p->next = q;
}

int main() {
    // ...
    insert(head, 0, 42);
    // ...
    return 0;
}

该函数接受三个参数:双循环链表的头结点,插入位置和插入的数据。如果插入位置超出了双循环链表的范围,该函数将不进行任何操作。

删除结点

用户可以在菜单列表中选择删除结点操作。该操作将删除指定位置的结点。

以下是删除结点的代码片段:

void delete(Node* head, int pos) {
    if (pos < 0) {
        printf("Invalid position!\n");
        return;
    }
    Node* p = head;
    for (int i = 0; i < pos; i++) {
        p = p->next;
        if (p == head) {
            printf("Out of range!\n");
            return;
        }
    }
    p->next->prev = p->prev;
    p->prev->next = p->next;
    free(p);
}

int main() {
    // ...
    delete(head, 0);
    // ...
}

该函数接受两个参数:双循环链表的头结点和要删除的结点的位置。如果删除位置超出了双循环链表的范围,该函数将不进行任何操作。

查找结点

用户可以在菜单列表中选择查找结点操作。该操作将在双循环链表中查找指定的数据,并返回该结点的位置。

以下是查找结点的代码片段:

int search(Node* head, int data) {
    Node* p = head->next;
    int i = 0;
    while (p != head) {
        if (p->data == data) {
            return i;
        }
        p = p->next;
        i++;
    }
    return -1;
}

int main() {
    // ...
    int pos = search(head, 42);
    // ...
    return 0;
}

该函数接受两个参数:双循环链表的头结点和要查找的数据。如果找到了该数据,该函数将返回该结点的位置,否则将返回 -1。

显示双循环链表

用户可以在菜单列表中选择显示双循环链表操作。该操作将显示双循环链表的所有结点。

以下是显示双循环链表的代码片段:

void display(Node* head) {
    Node* p = head->next;
    while (p != head) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

int main() {
    // ...
    display(head);
    // ...
    return 0;
}

该函数接受一个参数:双循环链表的头结点。该函数将遍历双循环链表,并打印出每个结点的数据。

完整代码

下面是实现以上操作的完整代码:

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

typedef struct Node {
    int data;
    struct Node* prev;
    struct Node* next;
} Node;

Node* createDLList() {
    Node* head = (Node*) malloc(sizeof(Node));
    head->prev = head;
    head->next = head;
    return head;
}

void insert(Node* head, int pos, int data) {
    if (pos < 0) {
        printf("Invalid position!\n");
        return;
    }
    Node* p = head;
    for (int i = 0; i < pos; i++) {
        p = p->next;
        if (p == head) {
            printf("Out of range!\n");
            return;
        }
    }
    Node* q = (Node*) malloc(sizeof(Node));
    q->data = data;
    q->prev = p;
    q->next = p->next;
    p->next->prev = q;
    p->next = q;
}

void delete(Node* head, int pos) {
    if (pos < 0) {
        printf("Invalid position!\n");
        return;
    }
    Node* p = head;
    for (int i = 0; i < pos; i++) {
        p = p->next;
        if (p == head) {
            printf("Out of range!\n");
            return;
        }
    }
    p->next->prev = p->prev;
    p->prev->next = p->next;
    free(p);
}

int search(Node* head, int data) {
    Node* p = head->next;
    int i = 0;
    while (p != head) {
        if (p->data == data) {
            return i;
        }
        p = p->next;
        i++;
    }
    return -1;
}

void display(Node* head) {
    Node* p = head->next;
    while (p != head) {
        printf("%d ", p->data);
        p = p->next;
    }
    printf("\n");
}

int main() {
    Node* head = createDLList();

    printf("== 双循环链表操作菜单 ==\n");
    printf("1. 创建双循环链表\n");
    printf("2. 插入结点\n");
    printf("3. 删除结点\n");
    printf("4. 查找结点\n");
    printf("5. 显示双循环链表\n");
    printf("6. 退出程序\n");

    int choice, pos, data, index;
    while (1) {
        printf("请选择操作:");
        scanf("%d", &choice);
        switch (choice) {
            case 1:
                printf("创建双循环链表\n");
                break;
            case 2:
                printf("插入结点\n");
                printf("请输入要插入的位置:");
                scanf("%d", &pos);
                printf("请输入要插入的数据:");
                scanf("%d", &data);
                insert(head, pos, data);
                break;
            case 3:
                printf("删除结点\n");
                printf("请输入要删除的位置:");
                scanf("%d", &pos);
                delete(head, pos);
                break;
            case 4:
                printf("查找结点\n");
                printf("请输入要查找的数据:");
                scanf("%d", &data);
                index = search(head, data);
                if (index == -1) {
                    printf("未找到该数据\n");
                } else {
                    printf("该数据在第 %d 个位置\n", index);
                }
                break;
            case 5:
                printf("显示双循环链表\n");
                display(head);
                break;
            case 6:
                printf("退出程序\n");
                return 0;
            default:
                printf("无效的操作\n");
                break;
        }
    }
}
总结

在本文中,我们学习了如何使用菜单驱动程序来实现双循环链表的所有操作,包括创建双循环链表、插入结点、删除结点、查找结点和显示双循环链表。菜单驱动程序可以方便地让用户进行交互操作,使程序更加友好。