欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构---带头结点的双向链表的增删查改1(C语言实现)

程序员文章站 2024-01-15 19:51:16
...

实现环境:LINUX

带头结点的增删查改相对而言比较简单,但是里边还是有些许坑,,稍不注意就掉进去,半天爬不出来。


数据结构---带头结点的双向链表的增删查改1(C语言实现)

                                                   将要实现的链表的图:

在双向链表中需要注意的是要注意两组指针的指向,即next和prev对应。双向链表已经可以说完成一半了。

数据结构---带头结点的双向链表的增删查改1(C语言实现)

在一个需要注意的坑是,在插入的时候需要注意的是一定要先new与node2然后在进行其他的操作,不然node1与node2之间指向断开,就会指向随机值,我就在这个坑了怕了一个多小时,才调试出来。

代码实现:

LinkList.c:

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

//实现创建
DLinkNode* DLinkListCreatNode(DLinkType value){
    DLinkNode* New_Node = (DLinkNode*)malloc(sizeof(DLinkNode));
    New_Node->data = value;
    New_Node->next = NULL;
    New_Node->prev = NULL;
    return New_Node;
}

//实现打印
void DLinkListPrint(DLinkNode* head,const char* msg){
    if(head == NULL){
        printf("非法输入\n");
        return;
    }
    printf("[*****%s*****]\n",msg);
    DLinkNode* cur = head->next;
    for(; cur != head; cur = cur->next){
        printf("[%c|%p]\t",cur->data,cur);
    }
    printf("\n");
    return;
}

//实现初始化
void DLinkListInit(DLinkNode** head){
    if(head == NULL){
        //非法输入
        return;
    } 
    *head =DLinkListCreatNode(0);
    (*head)->prev = *head;
    (*head)->next = *head;
    return;
}

//实现尾插
void DLinkListPushBack(DLinkNode* head, DLinkType value){
    if(head == NULL){
        //非法输入
        return;
    }
    DLinkNode* New_Node = DLinkListCreatNode(value);
    New_Node->data = value;
    DLinkNode* tail = head->prev;
   //此时三个值 tail(原来的末尾)  head(头)  New_Node(新加入的值,现在的末尾)
   //实现两组指针的指向prev和next的指向
   New_Node->next = head;
   head->prev = New_Node;
   New_Node->prev = tail;
   tail->next = New_Node;
}

//尾删
void DLinkListPopBack(DLinkNode* head){
    if(head == NULL){
        //非法输入
        return;
    }
    if(head->next == NULL){
        //空链表
        return;
    }
    DLinkNode* tailprev = head->prev->prev;
    free(tailprev->next);
    tailprev->next = head;
    head->prev = tailprev;
}

//头插
void DLinkListPushFront(DLinkNode*head, DLinkType value){
    if(head == NULL){
        //非法输入
        return;
    }
    DLinkNode* New_Node = DLinkListCreatNode(value);
    New_Node->next = head->next;
    New_Node->next->prev = New_Node;
    head->next = New_Node;
    New_Node->prev = head;
}

//头删
void DLinkListPopFront(DLinkNode* head){
    if(head == NULL){
        //非法输入
        return;
    }
    if(head->next == NULL){
        printf("空链表\n");
        return;
    }
    DLinkNode* to_deleted = head->next;
    head->next = to_deleted->next;
    to_deleted->next->prev = head;
    free(to_deleted);
}

//查找
DLinkNode* DLinkListFind(DLinkNode* head,DLinkType to_find){
    if(head == NULL){
        return;
    }
    DLinkNode* cur = head->next;;
    while(cur != head){
        if(cur->data == to_find){
                return cur;
        }
            cur = cur->next;
    }
    return NULL;
}

//在指定位置之前插入一个元素
void DLinkListInsert(DLinkNode* pos,DLinkType value){
    if(pos == NULL){
        return;
    }
    DLinkNode* New_Node = DLinkListCreatNode(value);
    DLinkNode* cur = pos->prev;
    cur->next = New_Node;
    New_Node->prev = cur;
    New_Node->next = pos;
    pos->prev = New_Node;
}

//在制定元素位置之后插入一个元素
void DLinkListInsertAfter(DLinkNode* pos,DLinkType value){
    if(pos == NULL){
        return;
    }
    DLinkNode* New_Node = DLinkListCreatNode(value);
    DLinkNode* Next_Node =pos->next;
    New_Node->next = Next_Node;
    Next_Node->prev = New_Node;
    pos->next = New_Node;
    New_Node->prev = pos;
}


//////////////////////////////////////////////
//********************************************
//*********Test Code**************************
//////////////////////////////////////////////

//测试尾插
void TestDLinkListPushBack(){
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushBack(head,'a');
    DLinkListPushBack(head,'b');
    DLinkListPushBack(head,'c');
    DLinkListPushBack(head,'d');
    DLinkListPrint(head,"尾插元素");
}

//测试尾删
void TestDLinkListPopBack(){
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushBack(head,'a');
    DLinkListPushBack(head,'b');
    DLinkListPushBack(head,'c');
    DLinkListPushBack(head,'d');
    DLinkListPopBack(head);
    DLinkListPrint(head,"尾删元素");
}

//测试头插
void TestDLinkListPushFront(){
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushFront(head,'a');
    DLinkListPushFront(head,'b');
    DLinkListPushFront(head,'c');
    DLinkListPushFront(head,'d');
    DLinkListPrint(head,"头插元素");
}

//测试头删
void TestDLinkListPopFront(){
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushBack(head,'a');
    DLinkListPushBack(head,'b');
    DLinkListPushBack(head,'c');
    DLinkListPushBack(head,'d');
    DLinkListPopFront(head);
    DLinkListPrint(head,"头删元素");
}

//测试在一个元素之前插入
void TestDLinkListInsert(){
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushBack(head,'a');
    DLinkListPushBack(head,'b');
    DLinkListPushBack(head,'c');
    DLinkListPushBack(head,'d');
    DLinkNode* pos = DLinkListFind(head,'c');
    DLinkListInsert(pos,'x');
    DLinkListPrint(head,"在元素之前插入一个元素");
}


//测试在一个元素之后插入
void TestDLinkListInsertAfter(){
    DLinkNode* head;
    DLinkListInit(&head);
    DLinkListPushBack(head,'a');
    DLinkListPushBack(head,'b');
    DLinkListPushBack(head,'c');
    DLinkListPushBack(head,'d');
    DLinkNode* pos = DLinkListFind(head,'c');
    DLinkListInsertAfter(pos,'x');
    DLinkListPrint(head,"在元素之后插入一个元素");
}

int main(){
    TestDLinkListPushBack();
    TestDLinkListPopBack();
    TestDLinkListPushFront();
    TestDLinkListPopFront();
    TestDLinkListInsert();
    TestDLinkListInsertAfter();
    return 0;
}

LinkList.h:

#pragma once

typedef char DLinkType;

typedef struct DLinkNode{
    DLinkType data;
    struct DLinkNode* next;     //指向下一个结点
    struct DLinkNode* prev;     //指向上一个结点
}DLinkNode;

//创建一个新结点
DLinkNode* DLinkListCreatNode(DLinkType value);

//打印
void DLinkListPrint(DLinkNode* head,const char* msg);

//初始化
void DLinkListInit(DLinkNode** head);

//尾插
void DLinkListPushBack(DLinkNode* head, DLinkType value);

//尾删
void DLinkListPopBack(DLinkNode* head);

//头插
void DLinkListPushFront(DLinkNode* head, DLinkType value);

//头删
void DLinkListPopFront(DLinkNode* head);