带头双向带环链表

  1. 初始化链表
  2. 尾插
  3. 尾删
  4. 头插
  5. 头删
  6. 查询元素
  7. 往指定位置之前插入一个元素
  8. 往指定位置之后插入一个元素
  9. 删除指定元素
  10. 删除指定元素的第一次出现
  11. 删除所有指定元素
  12. 求链表的长度
  13. 判断链表是否为空(0为空,1为非空)

dlinknode.h:

#pragma once

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

typedef char DLinkType;

//定义节点结构体
typedef struct DLinkNode{
    DLinkType data;
    struct DLinkNode* next;
    struct DLinkNode* prev; 
}DLinkNode;

//创建节点
DLinkNode* CreateNode();
//删除节点
void DeleteNode(DLinkNode* head);
//初始化
void DLinkNodeInit(DLinkNode** head);
//尾插
DLinkNode* DLinkNodePushBack(DLinkNode* head,DLinkType value);
//尾删
void DLinkNodePopBack(DLinkNode* head);
//头插
void DLinkNodePushTop(DLinkNode* head,DLinkType value);
//头删
void DLinkNodePopTop(DLinkNode* head);
//查询元素
DLinkNode* DLinkNodeFind(DLinkNode* head,DLinkType value);
//往指定位置之前插入一个元素
void DLinkNodeInsert(DLinkNode* pos,DLinkType value);
//往指定位置之后插入一个元素
void DLinkNodeInsertAfter(DLinkNode* pos,DLinkType value);
//删除指定元素
void DLinkNodeErase(DLinkNode* head,DLinkNode* pos);
//删除指定元素的第一次出现
void DLinkNodeRemove(DLinkNode* head,DLinkType value);
//删除所有指定元素
void DLinkNodeRemoveAll(DLinkNode* head,DLinkType value);
//求链表的长度
size_t DLinkNodeSize(DLinkNode* head);
//判断链表是否为空(0为空,1为非空)
int DLinkNodeEmpty(DLinkNode* head);

dlinknode.c:

#include "dlinknode.h"

//创建节点
DLinkNode* CreateNode()
{
    //创建节点malloc,切记别忘了free
    DLinkNode* head = (DLinkNode*)malloc(sizeof(DLinkNode));
    head->next = NULL;
    head->prev = NULL;
}

//删除节点
void DeleteNode(DLinkNode* node)
{
    free(node);
    node = NULL;
}

//初始化
void DLinkNodeInit(DLinkNode** head)
{
    //因为是带头节点,所以创建一个头结点,自己成环即可
    *head = CreateNode();
    (*head)->next = *head;
    (*head)->prev = *head;
}
//尾插
DLinkNode* DLinkNodePushBack(DLinkNode* head,DLinkType value)
{
    if(head == NULL)
    {
        return;
    }
    DLinkNode* cur = CreateNode();
    cur->data = value;

    //另外定义俩个指针,以便方便插入一个值
    DLinkNode* file = head;
    DLinkNode* last = head->prev;
    cur->prev = last;
    cur->next = file;
    file->prev = cur;
    last->next = cur;
    return cur;
}
//尾删
void DLinkNodePopBack(DLinkNode* head)
{
    if(head == NULL)
    {
        return;
    }
    //另外定义一个需要删除的节点
    DLinkNode* to_delete = head->prev;
    DLinkNode* cur = to_delete->prev;
    DLinkNode* file = head;
    cur->next = file;
    file->prev = cur;
    DeleteNode(to_delete);
}
//头插
void DLinkNodePushTop(DLinkNode* head,DLinkType value)
{
    if(head == NULL)
    {
        return;
    }

    DLinkNode* new_node = CreateNode();
    new_node->data = value;
    //和尾插类似,由于这个是双向的,所以比单链表要简单的,不需要考虑太多
    DLinkNode* cur = head->next;
    DLinkNode* file = head;

    new_node->next = cur;
    new_node->prev = file;
    cur->prev = new_node;
    file->next = new_node;
}

//头删
void DLinkNodePopTop(DLinkNode* head)
{
    if(head == NULL)
    {
        return;
    }

    DLinkNode* to_delete = head->next;
    DLinkNode* cur = to_delete->next;
    DLinkNode* file = head;

    file->next = cur;
    DeleteNode(to_delete);
}
//查找元素
DLinkNode* DLinkNodeFind(DLinkNode* head,DLinkType value)
{
    if(head == NULL)
    {
        return;
    }
    //思路是:定义一个遍历的指针,判断是否为需要查找的值
    DLinkNode* cur = head;
    while(cur->next != head)
    {
        if(cur->data == value)
        {
            return cur;
        }
        cur = cur->next;
    }
    if(cur->data == value)
    {
        return cur;
    }
    return NULL;
}
//在pos前插入值(需满足pos在环内),不在和上面的查询类似
void DLinkNodeInsert(DLinkNode* pos,DLinkType value)
{
    if(pos == NULL)
    {
        return;
    }
    //和上面的头插尾插类似
    DLinkNode* new_node = CreateNode();
    new_node->data = value;
    DLinkNode* cur = pos->prev;
    cur->next = new_node;
    pos->prev = new_node;
    new_node->next = pos;
    new_node->prev = cur;
}
//在pos之后插入一个值
void DLinkNodeInsertAfter(DLinkNode*pos,DLinkType value)
{
    if(pos == NULL)
    {
        return;
    }
    //和上面类似,这些你要是写出来一个,其他的在纸上画一下,很容易搞懂的
    DLinkNode* new_node = CreateNode();
    new_node->data = value;
    DLinkNode* cur = pos->next;
    pos->next = new_node;
    cur->prev = new_node;
    new_node->next = cur;
    new_node->prev = pos;
}
//删除指定元素
void DLinkNodeErase(DLinkNode* head,DLinkNode* pos)
{
    if(head == NULL || pos == NULL)
    {
        return;
    }
    //还是老思路,定义一个遍历指针来判断值
    DLinkNode* cur = head->next;
    while(cur != pos && cur != head)
    {
        cur = cur->next;
    }
    if(cur == pos)
    {
        DLinkNode* file = pos->next;
        cur = cur->prev;
        cur->next = file;
        file->prev = cur;
        DeleteNode(pos);
    }
}
//删除有多个值的第一次出现,和上面删除指定值一样
void DLinkNodeRemove(DLinkNode* head,DLinkType value)
{
    if(head == NULL)
    {
        return;
    }

    DLinkNode* cur = head->next;

    while(cur->data != value && cur != head)
    {
        cur = cur->next;
    }
    if(cur->data == value)
    {
        DLinkNode* file = cur->next;
        DLinkNode* to_delete = cur;
        cur = cur->prev;
        cur->next = file;
        file->prev = cur;
        DeleteNode(to_delete);
    }
}
//删除所有指定的值,上面的是找到一个删除了直接退出,那这个删完继续遍历直到遍历一周,找到需要删除的值删除就ok
void DLinkNodeRemoveAll(DLinkNode* head,DLinkType value)
{
    if(head == NULL)
    {
        return;
    }
    DLinkNode* cur = head->next;
    while(cur != head)
    {
        if(cur->data != value)
        {
            cur = cur->next;
        }
        else
        {
            DLinkNode* file = cur->next;
            DLinkNode* to_delete = cur;
            cur = cur->prev;
            cur->next = file;
            file->prev = cur;
            DeleteNode(to_delete);
        }
    }
}
//求链表的长度,思路:还是遍历以便用计数器++
size_t DLinkNodeSize(DLinkNode* head)
{
    if(head == NULL)
    {
        return 0;
    }
    size_t count = 0;
    DLinkNode* cur = head->next;
    while(cur != head)
    {
        cur = cur->next;
        count++;
    }
    return count;
}
//判断是否为空,看头节点的next是否是它自己,是则为空,否则不为空
int DLinkNodeEmpty(DLinkNode* head)
{
    if(head == NULL)
    {
        return 0;
    }
    DLinkNode* cur = head;
    if(cur->next == head)
    {
        return 0;
    }
    return 1;
}

//------------------------------------------------------------
//-----测试函数
//------------------------------------------------------------


//测试函数嘛需得考虑各种情况,所以我们要保证函数的健壮性,就得考虑好各种情况以及特殊的情况
#define LINE printf("-------------------------------------------------\n");

void DLinkNodePrint(DLinkNode* head,const char* msg)
{
    printf("%s\n",msg);
    DLinkNode* cur = head->next;
    printf("[头|%p]",&(head->data));
    printf("<->");
    int i = 0;
    while(cur->next != head)
    {
        printf("[%c|%p]",cur->data,&(cur->data));
        printf("<->");
        cur = cur->next;
        i++;
    }
    if(cur->next == head && i != 0)
    {
        printf("[%c|%p]",cur->data,&(cur->data));
        printf("<->");
    }
    printf("[头|%p]\n",&(head->data));
}

void testDLinkNodePushBack()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'d');

    DLinkNodePrint(head,"DLinkNodePushBack");
}

void testDLinkNodePopBack()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'d');

    DLinkNodePopBack(head);
    DLinkNodePrint(head,"DLinkNodePopBack");
}

void testDLinkNodePushTop()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');

    DLinkNodePushTop(head,'z');
    DLinkNodePrint(head,"DLinkNodePushTop");
}

void testDLinkNodePopTop()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'d');

    DLinkNodePopTop(head);
    DLinkNodePrint(head,"DLinkNodePopTop");
}

void testDLinkNodeFind()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'d');

    DLinkNode* cur = DLinkNodeFind(head,'c');
    DLinkNodePrint(head,"DLinkNodeFind");
    if(cur == NULL)
    {
        printf("not find !\n");
    }
    else
    {
        printf("find it:[%c|%p]\n",cur->data,&(cur->data));
    }
}

void testDLinkNodeInsert()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNode* pos = DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');

    DLinkNodePrint(head,"DLinkNodeInsert");
    DLinkNodeInsert(pos,'z');
    DLinkNodePrint(head,"DLinkNodeInsert");
}

void testDLinkNodeInsertAfter()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNode* pos = DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');

    DLinkNodePrint(head,"DLinkNodeInsertAfter");
    DLinkNodeInsertAfter(pos,'z');
    DLinkNodePrint(head,"DLinkNodeInsertAfter");
}

void testDLinkNodeErase()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNode* pos = DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'d');

    DLinkNodeErase(head,pos);
    DLinkNodePrint(head,"DLinkNodeErase");
}

void testDLinkNodeRemove()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'d');

    DLinkNodeRemove(head,'c');
    DLinkNodePrint(head,"DLinkNodeRemove");
}

void testDLinkNodeRemoveAll()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'d');
    DLinkNodePushBack(head,'c');

    DLinkNodeRemoveAll(head,'c');
    DLinkNodePrint(head,"DLinkNodeRemoveAll");
}

void testDLinkNodeSize()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'d');

    int ret = DLinkNodeSize(head);
    DLinkNodePrint(head,"DLinkNodeSize");
    printf("DLinkNodeSize is :%d\n",ret);
}

void testDLinkNodeEmpty()
{
    LINE;
    DLinkNode* head = NULL;
    DLinkNodeInit(&head);

    DLinkNodePushBack(head,'a');
    DLinkNodePushBack(head,'c');
    DLinkNodePushBack(head,'b');
    DLinkNodePushBack(head,'c');

    int ret = DLinkNodeEmpty(head);
    DLinkNodePrint(head,"DLinkNodeEmpty");
    printf("%d\n",ret);
}

int main()
{
    testDLinkNodePushBack();
    testDLinkNodePopBack();
    testDLinkNodePushTop();
    testDLinkNodePopTop();
    testDLinkNodeFind();
    testDLinkNodeInsert();
    testDLinkNodeInsertAfter();
    testDLinkNodeErase();
    testDLinkNodeRemove();
    testDLinkNodeRemoveAll();
    testDLinkNodeSize();
    testDLinkNodeEmpty();
    return 0;
}













这里写图片描述
这里写图片描述

阅读更多 登录后自动展开
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页