温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C语言怎么实现线性表中的带头双向循环链表

发布时间:2022-03-29 17:47:28 阅读:135 作者:iii 栏目:开发技术
C语言开发者专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

C语言怎么实现线性表中的带头双向循环链表

目录

  1. 引言
  2. 双向循环链表的基本概念
  3. 带头双向循环链表的结构设计
  4. 带头双向循环链表的基本操作
  5. 完整代码示例
  6. 总结

引言

在数据结构中,链表是一种非常基础且重要的线性结构。链表有多种形式,如单向链表、双向链表、循环链表等。本文将详细介绍如何在C语言中实现一个带头节点的双向循环链表。带头节点的双向循环链表结合了双向链表和循环链表的优点,具有较高的灵活性和效率。

双向循环链表的基本概念

双向循环链表是一种特殊的链表结构,它具备以下特点:

  1. 双向性:每个节点有两个指针,分别指向前驱节点和后继节点。
  2. 循环性:链表的最后一个节点的后继指针指向链表的第一个节点,第一个节点的前驱指针指向最后一个节点。
  3. 带头节点:链表中有一个特殊的节点,称为头节点,它不存储实际数据,仅用于简化链表操作。

带头双向循环链表的结构设计

在C语言中,我们可以通过结构体来定义双向循环链表的节点结构。每个节点包含三个部分:

  • 数据域:用于存储节点的数据。
  • 前驱指针:指向当前节点的前驱节点。
  • 后继指针:指向当前节点的后继节点。
typedef struct Node {
    int data;               // 数据域
    struct Node* prev;      // 前驱指针
    struct Node* next;      // 后继指针
} Node;

带头双向循环链表的基本操作

初始化链表

初始化链表时,我们需要创建一个头节点,并将其前驱和后继指针都指向自身,形成一个空的循环链表。

Node* createList() {
    Node* head = (Node*)malloc(sizeof(Node));
    if (head == NULL) {
        printf("Memory allocation failed!\n");
        return NULL;
    }
    head->prev = head;
    head->next = head;
    return head;
}

插入节点

在带头双向循环链表中插入节点时,通常有以下几种情况:

  1. 在链表头部插入节点:将新节点插入到头节点之后。
  2. 在链表尾部插入节点:将新节点插入到头节点之前。
  3. 在指定位置插入节点:在链表的某个节点之后插入新节点。

以下是插入节点的代码示例:

void insertAfter(Node* head, int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (newNode == NULL) {
        printf("Memory allocation failed!\n");
        return;
    }
    newNode->data = data;

    newNode->next = head->next;
    newNode->prev = head;
    head->next->prev = newNode;
    head->next = newNode;
}

void insertBefore(Node* head, int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (newNode == NULL) {
        printf("Memory allocation failed!\n");
        return;
    }
    newNode->data = data;

    newNode->prev = head->prev;
    newNode->next = head;
    head->prev->next = newNode;
    head->prev = newNode;
}

void insertAt(Node* head, int position, int data) {
    Node* current = head->next;
    int count = 0;
    while (current != head && count < position) {
        current = current->next;
        count++;
    }
    if (count == position) {
        Node* newNode = (Node*)malloc(sizeof(Node));
        if (newNode == NULL) {
            printf("Memory allocation failed!\n");
            return;
        }
        newNode->data = data;

        newNode->next = current;
        newNode->prev = current->prev;
        current->prev->next = newNode;
        current->prev = newNode;
    } else {
        printf("Position out of range!\n");
    }
}

删除节点

删除节点时,我们需要找到要删除的节点,并调整其前驱和后继节点的指针,使其跳过该节点。以下是删除节点的代码示例:

void deleteNode(Node* head, int data) {
    Node* current = head->next;
    while (current != head) {
        if (current->data == data) {
            current->prev->next = current->next;
            current->next->prev = current->prev;
            free(current);
            return;
        }
        current = current->next;
    }
    printf("Node with data %d not found!\n", data);
}

查找节点

查找节点时,我们可以从头节点开始遍历链表,直到找到目标节点或回到头节点为止。以下是查找节点的代码示例:

Node* findNode(Node* head, int data) {
    Node* current = head->next;
    while (current != head) {
        if (current->data == data) {
            return current;
        }
        current = current->next;
    }
    return NULL;
}

遍历链表

遍历链表时,我们可以从头节点开始,依次访问每个节点的数据域,直到回到头节点为止。以下是遍历链表的代码示例:

void traverseList(Node* head) {
    Node* current = head->next;
    while (current != head) {
        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* createList() {
    Node* head = (Node*)malloc(sizeof(Node));
    if (head == NULL) {
        printf("Memory allocation failed!\n");
        return NULL;
    }
    head->prev = head;
    head->next = head;
    return head;
}

void insertAfter(Node* head, int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (newNode == NULL) {
        printf("Memory allocation failed!\n");
        return;
    }
    newNode->data = data;

    newNode->next = head->next;
    newNode->prev = head;
    head->next->prev = newNode;
    head->next = newNode;
}

void insertBefore(Node* head, int data) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (newNode == NULL) {
        printf("Memory allocation failed!\n");
        return;
    }
    newNode->data = data;

    newNode->prev = head->prev;
    newNode->next = head;
    head->prev->next = newNode;
    head->prev = newNode;
}

void insertAt(Node* head, int position, int data) {
    Node* current = head->next;
    int count = 0;
    while (current != head && count < position) {
        current = current->next;
        count++;
    }
    if (count == position) {
        Node* newNode = (Node*)malloc(sizeof(Node));
        if (newNode == NULL) {
            printf("Memory allocation failed!\n");
            return;
        }
        newNode->data = data;

        newNode->next = current;
        newNode->prev = current->prev;
        current->prev->next = newNode;
        current->prev = newNode;
    } else {
        printf("Position out of range!\n");
    }
}

void deleteNode(Node* head, int data) {
    Node* current = head->next;
    while (current != head) {
        if (current->data == data) {
            current->prev->next = current->next;
            current->next->prev = current->prev;
            free(current);
            return;
        }
        current = current->next;
    }
    printf("Node with data %d not found!\n", data);
}

Node* findNode(Node* head, int data) {
    Node* current = head->next;
    while (current != head) {
        if (current->data == data) {
            return current;
        }
        current = current->next;
    }
    return NULL;
}

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

int main() {
    Node* head = createList();
    insertAfter(head, 10);
    insertAfter(head, 20);
    insertBefore(head, 5);
    insertAt(head, 1, 15);

    printf("List after insertions: ");
    traverseList(head);

    deleteNode(head, 15);
    printf("List after deletion: ");
    traverseList(head);

    Node* found = findNode(head, 20);
    if (found != NULL) {
        printf("Node with data 20 found!\n");
    } else {
        printf("Node with data 20 not found!\n");
    }

    return 0;
}

总结

本文详细介绍了如何在C语言中实现一个带头节点的双向循环链表。通过定义节点结构体,并实现链表的初始化、插入、删除、查找和遍历等基本操作,我们可以灵活地管理链表中的数据。带头双向循环链表在实际应用中具有较高的效率和灵活性,适用于需要频繁插入和删除操作的场景。希望本文能帮助读者更好地理解和掌握双向循环链表的实现方法。

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI

开发者交流群×