【推荐】数据结构:双向链表(带头节点带环)的实现

C语言实现双向链表的基本功能
1.尾插

2.尾删

3.头插

4.头删

5.查找指定元素的位置

6.在指定位置之前插入元素

7.在指定位置之后插入元素

8.删除指定位置的元素

9.删除指定值的元素

10.删除指定所有相同的元素

11.求链表的长度

12.判断链表是否为空

头文件


文件名dlinklist.h
#pragma once   //防止头文件重复定义

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

typedef char DLinktype;

typedef struct DLinkNode
{
    DLinktype data;     //  存放数据
    struct DLinkNode* next;   //定义后一个节点
    struct DLinkNode* prev;    //定义前一个节点
}DLinkNode;

//初始化函数
void DLinklistInit(DLinkNode** phead); 

//链表尾插
DLinkNode*  DLinklistPushback(DLinkNode* head, DLinktype value);  

//链表尾删
void  DLinklistPopback(DLinkNode* head);

//链表头插
void DLinklistPushfront(DLinkNode* head, DLinktype value);

//链表头删
void  DLinklistPopfront(DLinkNode* head);

//查找指定元素的位置
DLinkNode*  DLinklistFind(DLinkNode* head,  DLinktype value);

// 在指定位置之前插入元素
void DLinklistInsert(DLinkNode* head, DLinkNode* pos, DLinktype value);


// 在指定位置之后插入元素
void DLinklistInsertafter(DLinkNode* head, DLinkNode* pos, DLinktype value);

//删除指定位置的元素
void DLinklistErase(DLinkNode*head, DLinkNode* to_delete);

//删除指定值的元素
void DLinklistRemove(DLinkNode* head, DLinktype to_remove);

//删除指定值的所有元素
void DLinklistRemoveall(DLinkNode* head, DLinktype to_remove);

//求链表的长度
size_t DLinklistSize(DLinkNode* head);

//判断链表是否为空
int DLinklistEmpty(DLinkNode* head);

功能实现

文件名 dlinklist.c


#include"dlinklist.h"
//创建新节点

DLinkNode* DLinkNodeCreat(DLinktype value)
{
    DLinkNode* new = (DLinkNode*)malloc(sizeof(DLinkNode));  //创建节点申请空间
    new->data = value;              //
    new->next = NULL;
    new->prev = NULL;
    return new;  
}

//销毁节点
void DLinkNodeDestroy(DLinkNode* node)
{
    free(node);     
    node = NULL;
}
//初始化函数
void DLinklistInit(DLinkNode** phead)
{
    if (phead == NULL)
    {
        printf("非法输入");
        return;
    }
    *phead = DLinkNodeCreat(0);  //创建一个不具有实际意义的头节点,
    (*phead)->next = *phead;         
    (*phead)->prev = *phead;  
}


//链表尾插
DLinkNode*  DLinklistPushback(DLinkNode* head, DLinktype value)
{
    if (head == NULL)
    {
        printf("非法输入");
        return NULL;
    }
    DLinkNode* new = DLinkNodeCreat(value);
    DLinkNode* tail = head->prev;
    //head 2-2 new 
    new->next = head;
    head->prev = new;
    //tail 2-2 new 
    tail->next = new;
    new->prev = tail;
    return new;
}

//链表尾删
void  DLinklistPopback(DLinkNode* head)
{
    if (head == NULL)
    {
        printf("非法输入");
        return;
    }
    if (head->next == head || head->prev == head)  
    {
        printf("空链表");
        return;
    }
    DLinkNode* lastone = head->prev;
    DLinkNode* lasttwo = lastone->prev;
    lasttwo->next = head;
    head->prev = lasttwo;
    DLinkNodeDestroy(lastone);

}

//链表头插
void DLinklistPushfront(DLinkNode* head, DLinktype value)
{
    if (head == NULL)
    {
        printf("非法输入");
            return;
    }
    DLinkNode* new = DLinkNodeCreat(value);
    DLinkNode* second = head->next;
    // sencond new
    new->next = second;
    second->prev = new;
    // head new
    head->next = new;
    new->prev = head;
}

//链表头删
void  DLinklistPopfront(DLinkNode* head)
{
    if (head == NULL)
    {
        printf("非法输入");
        return;
    }
    if (head->next == head || head->prev == head)
    {
        printf("空链表");
        return;
    }
    DLinkNode* second = head->next;
    DLinkNode* third = second->next;
    head->next = third;
    third->prev = head;
    DLinkNodeDestroy(second);
}

//查找指定元素的位置
DLinkNode*  DLinklistFind(DLinkNode* head,  DLinktype to_find)
{
    if (head == NULL)
    {
        printf("非法输入");
        return NULL;
    }
    DLinkNode* cur = head->next;
    while (cur != head)
    {
        if (cur->data==to_find)
        {
            return cur;
        }
        cur = cur->next;
    }
    return NULL;
}

// 在指定位置之前插入元素
void DLinklistInsert(DLinkNode* head, DLinkNode* pos, DLinktype value)
{
    if (head == NULL || pos == NULL)
    {
        printf("非法输入");
        return;
    }
    DLinkNode* pospre = pos->prev;
    DLinkNode* new = DLinkNodeCreat(value);
    //pospre  new
    new->prev = pospre;
    pospre->next = new;
    //new  pos
    new->next = pos;
    pos->prev = new;

}


// 在指定位置之后插入元素
void DLinklistInsertafter(DLinkNode* head, DLinkNode* pos, DLinktype value)
{
    if (head == NULL || pos == NULL)
    {
        printf("非法输入");
        return;
    }
    DLinkNode* new = DLinkNodeCreat(value);
    DLinkNode* posafter = pos->next;
    // pos  new 
    pos->next = new;
    new->prev = pos;
    //new posafter
    new->next = posafter;
    posafter->prev = new;
}

//删除指定位置的元素
void DLinklistErase(DLinkNode*head, DLinkNode* to_delete)
{
    if (head == NULL || to_delete == NULL)
    {
        printf("非法输入");
        return;
    }
    DLinkNode* after = to_delete->next;
    DLinkNode* before = to_delete->prev;
    before->next=after;
    after->prev = before;
    DLinkNodeDestroy(to_delete);
}

//删除指定值的元素
void DLinklistRemove(DLinkNode* head, DLinktype to_remove)
{
    if (head == NULL )
    {
        printf("非法输入");
        return;
    }
    DLinkNode* pos = DLinklistFind(head, to_remove);
    DLinklistErase(head, pos);
}

//删除指定值的所有元素
void DLinklistRemoveall(DLinkNode* head, DLinktype value)
{
    if (head == NULL)
    {
        printf("非法输入");
        return;
    }
    DLinkNode* cur = head->next;
    while (cur != head)
    {
        if (cur->data == value)
        {
            DLinkNode* before = cur->prev;
            DLinkNode* after = cur->next;
            before->next = after;
            after->prev = before;
            DLinkNode* tmp = cur;
            DLinkNodeDestroy(tmp);
            cur = before;
        }
        cur = cur->next;
    }
}

//求链表的长度
size_t DLinklistSize(DLinkNode* head)
{
    if (head == NULL)
    {
        printf("非法输入");
        return 0;
    }
    size_t count = 0;
    DLinkNode* cur = head->next;
    while (cur != head)
    {
        count++;
        cur = cur->next;
    }
    return count;
}

//判断链表是否为空
int DLinklistEmpty(DLinkNode* head)
{
    if(head == NULL){
        //非法输入
        return -1;
    }
    if (head->next == head){
        return 1;
    }
    return 0;
}

测试代码

文件名test.c
#include"linknode.h"

#define FUNCTION() printf("******  %s  ***********\n",__FUNCTION__) ;


void Printchar(DLinkNode* head, const char *msg)
{
    printf("[%s]:\n", msg);
    if (head == NULL)
    {
        return;
    }
    DLinkNode* cur = head->next;
    //正序打印
    while (cur != head)
    {
        printf("[%c|%p]", cur->data, cur);
        cur = cur->next;
    }
    printf("\n");
    //逆序打印
    DLinkNode* ret = head->prev;
    while (ret != head)
    {
        printf("[%c|%p]", ret->data, ret);
        ret = ret->prev;
    }
    printf("\n");
}

void TestDInit()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
}
void TestPushback()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    Printchar(head, "尾插四个元素");
}

void TestPopback()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    Printchar(head, "先插四个元素");

    DLinklistPopback(head);
    DLinklistPopback(head);
    Printchar(head, "尾删两个元素");

    DLinklistPopback(head);
    DLinklistPopback(head);
    Printchar(head, "再尾删两个元素");

    DLinklistPopback(head);
    Printchar(head, "尝试对空链表尾删");

}
void TestPushfront()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushfront(head, 'a');
    DLinklistPushfront(head, 'b');
    DLinklistPushfront(head, 'c');
    DLinklistPushfront(head, 'd');
    Printchar(head, "头插四个元素");
}

void TestPopfront()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    Printchar(head, "尾插四个元素");

    DLinklistPopfront(head);
    DLinklistPopfront(head);
    Printchar(head, "头删两个元素");

    DLinklistPopfront(head);
    DLinklistPopfront(head);
    Printchar(head, "再头删两个元素");

    DLinklistPopfront(head);
    DLinklistPopfront(head);
    Printchar(head, "尝试对空链表头删");
}

void TestFind()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    Printchar(head, "尾插四个元素");
    DLinkNode* cur = DLinklistFind(head, 'c');
    printf("元素c的位置:%p\n", cur);
}

void TestInsert()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    Printchar(head, "尾插四个元素");
    DLinkNode* pos = DLinklistFind(head, 'c');
    DLinklistInsert(head, pos, 'X');
    Printchar(head, "C之前插入元素X");
}

void TestInsertafter()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    Printchar(head, "尾插四个元素");
    DLinkNode* pos = DLinklistFind(head, 'c');
    DLinklistInsertafter(head, pos, 'Y');
    Printchar(head, "C之后插入元素Y");
}


void TestErase()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    Printchar(head, "尾插四个元素");
    DLinkNode* pos = DLinklistFind(head, 'c');
    DLinklistErase(head, pos);
    Printchar(head, "删除元素c");
}
void TestRemove()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    Printchar(head, "尾插四个元素");
    DLinklistRemove(head, 'c');
    Printchar(head, "删除元素c");
}

void TestRemoveall()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    DLinklistPushback(head, 'c');
    Printchar(head, "尾插五个元素");

    DLinklistRemoveall(head, 'c');
    Printchar(head, "删除元素c");
}

void TestSize()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    Printchar(head, "尾插四个元素");

    size_t count = DLinklistSize(head);
    printf("链表的长度为:%lu\n", count);
}

void TestEmpty()
{
    FUNCTION();
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushback(head, 'a');
    DLinklistPushback(head, 'b');
    DLinklistPushback(head, 'c');
    DLinklistPushback(head, 'd');
    Printchar(head, "尾插四个元素");

    int ret = DLinklistEmpty(head);
    printf("expect result is 0,actual is %d\n", ret);
}

int main()
{
    TestPushback();
    TestPopback();
    TestPushfront();
    TestPopfront();
    TestFind();
    TestInsert();
    TestInsertafter();
    TestErase();
    TestRemove();
    TestRemoveall();
    TestSize();
    TestEmpty();
    return 0;
}

这里写图片描述

这里写图片描述

这里写图片描述

猜你喜欢

转载自blog.csdn.net/yu876876/article/details/79983032