!-- 带头结点带环的双向链表的相关操作实现 --!

带头结点的链表:创建一个新结点表示空链表,该结点即为头结点,且头结点中的数据无任何意义

不带头结点的链表:用NULL表示空链表

头结点的好处:不用考虑头指针的指向问题,只要头指针初始化完成,就永远指向头结点,仅在要销毁整个链表时考虑

DLinklist.h 

//带头结点、带环、双向链表
#pragma once
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>

#define SHOW_NAME printf("\n===================%s=================\n",__FUNCTION__);

typedef char DLinkType;
typedef struct DLinkNode
{
    DLinkType data;
    struct DLinkNode* prev;
    struct DLinkNode* next;
}DLinkNode;

DLinkNode* CreateDLinkNode(DLinkType value);//创建一个新结点
void DLinklistInit(DLinkNode** phead);//初始化
void DLinklistPushBack(DLinkNode* head,DLinkType value);//尾插
void DestroyNode(DLinkNode* node);//销毁结点
void DLinklistPopBack(DLinkNode* head);//尾删
void DLinklistPushFront(DLinkNode* head,DLinkType value);//头插
void DLinklistPopFront(DLinkNode* head);//头插
DLinkNode* DLinklistFind(DLinkNode* head,DLinkType value);//查找值为value的结点,找到返回结点,找不到返回NULL
void DLinklistInsertBefore(DLinkNode* head,DLinkNode* pos,DLinkType value);//向pos位置前插入
void DLinklistInsertAfter(DLinkNode* head,DLinkNode* pos,DLinkType value);//向pos位置后插入
void DLinklistErase(DLinkNode* head,DLinkNode* pos);//删除pos位置结点
void DLinklistRemove(DLinkNode* head,DLinkType value);//删除值为value的结点
void DLinklistRemoveAll(DLinkNode* head,DLinkType value);//删除值为value的所有结点
void DLinklistDestroy(DLinkNode** phead);//销毁结点

DLinklist.c

#include "DLinklist.h"

DLinkNode* CreateDLinkNode(DLinkType value)//创建一个新的结点
{
    DLinkNode* new_node = (DLinkNode*)malloc(sizeof(DLinkNode));
    new_node->data = value;
    new_node->prev = new_node;//要实现带环,这里将结点的两个指针都指向自己
    new_node->next = new_node;
    return new_node;
}

void DLinklistInit(DLinkNode** phead)//初始化
{
    if(phead == NULL)//非法操作
        return;
    *phead = CreateDLinkNode(0);//头结点中的数据无任何意义,任意置
}

void DLinklistPushBack(DLinkNode*head,DLinkType value)//尾插结点(修改四个指针)
{
    if(head == NULL)//非法操作
        return;
    //不用考虑链表为空的情况,它可以合并到以下代码
    DLinkNode* new_node = CreateDLinkNode(value);
    DLinkNode* tail = head->prev;
    head->prev = new_node;//head与new_node
    new_node->next = head;
    tail->next = new_node;//tail与new_node
    new_node->prev = tail;
    return;
}

void DestroyNode(DLinkNode* node)//销毁结点
{
    free(node);
}

void DLinklistPopBack(DLinkNode* head)//尾删(修改两个指针)
{
    if(head == NULL)//非法操作
        return;
    if(head->prev == head)//空链表
    //if(head->next == head)
        return;
    DLinkNode* to_delete = head->prev;
    DLinkNode* tail = to_delete->prev;
    head->prev = tail;
    tail->next = head;
    DestroyNode(to_delete);
    return;
}

void DLinklistPushFront(DLinkNode* head,DLinkType value)//头插(修改四个指针)
{
    if(head == NULL)//非法操作
        return;
    DLinkNode* new_node = CreateDLinkNode(value);
    DLinkNode* next_node = head->next;
    head->next = new_node;//head与new_node
    new_node->prev = head;
    new_node->next = next_node;//next_node与new_node
    next_node->prev = new_node;
    return;
}

void DLinklistPopFront(DLinkNode* head)//头删(修改两个指针)
{
    if(head == NULL)//非法操作
        return;
    if(head->prev == head)//空链表
        return;
    DLinkNode* to_delete = head->next;
    DLinkNode* next_node = to_delete->next;
    head->next = next_node;
    next_node->prev = head;
    DestroyNode(to_delete);
    return;
}

void DLinklistPrint(DLinkNode* head,const char* msg)//打印链表
{
    printf("[%s]\n",msg);
    DLinkNode* cur = head->next;
    for(; cur!=head; cur=cur->next)//正向打印,判断所有的next指针指向是否正确
    {
        printf("[%c|%p] ",cur->data,cur);
    }
    printf("\n");
    for(cur=head->prev; cur!=head; cur=cur->prev)//逆向打印,判断所有的prev指向是否正确
    {
        printf("[%c|%p] ",cur->data,cur);
    }
    printf("\n");
}

DLinkNode* DLinklistFind(DLinkNode* head,DLinkType value)//查找值为value的结点
{
    if(head == NULL)//非法操作
        return;
    DLinkNode* cur = head->next;
    while(cur != head)
    {
        if(cur->data == value)
            return cur;
        cur = cur->next;
}
    return NULL;
}

void DLinklistInsertBefore(DLinkNode* head,DLinkNode* pos,DLinkType value)//向pos位置前插入元素
{
    if(head == NULL || pos == NULL)//非法操作 
        return;
    DLinkNode* new_node = CreateDLinkNode(value);
    DLinkNode* pre = pos->prev;
    pre->next = new_node;
    new_node->prev = pre;
    new_node->next = pos;
    pos->prev = new_node;
    return;
}

void DLinklistInsertAfter(DLinkNode* head,DLinkNode* pos,DLinkType value)//向pos位置后插入元素
{
    if(head == NULL || pos == NULL)//非法操作 
        return;
    DLinkNode* new_node = CreateDLinkNode(value);
    DLinkNode* next_node = pos->next;
    pos->next = new_node;
    new_node->prev = pos;
    new_node->next = next_node;
    next_node->prev = new_node;
    return;
}

void DLinklistErase(DLinkNode* head,DLinkNode* pos)//删除pos位置的结点
{
    if(head == NULL || pos == NULL)//非法操作
        return;
    if(head == pos)//非法操作,head指向的元素不能释放,除非在销毁整个链表
        return;
    DLinkNode* pre = pos->prev;
    DLinkNode* nex = pos->next;
    pre->next = nex;
    nex->prev = pre;
    DestroyNode(pos);
    return;
}

void DLinklistRemove(DLinkNode* head,DLinkType value)//删除值为value的结点
{
    if(head == NULL)
        return;
    DLinkNode* cur = head->next;
    while(cur != head)
    {
        if(cur->data == value)
        {
            DLinkNode* pre = cur->prev;
            DLinkNode* nex = cur->next;
            pre->next = nex;
            nex->prev = pre;
            DestroyNode(cur);
            return;
        }
        cur = cur->next;
    }
    return;
   // DLinkNode* to_delete = DLinklistFind(head,value);
   // if(to_delete == NULL)
   //     return;
   // DLinklistErase(head,to_delete);
   // return;
}

void DLinklistRemoveAll(DLinkNode* head,DLinkType value)//删除值为value的所有结点
{
    if(head == NULL)
        return;
    DLinkNode* cur = head->next;
    while(cur != head)
    {
        if(cur->data == value)
        {
            DLinkNode* pre = cur->prev;
            DLinkNode* nex = cur->next;
            pre->next = nex;
            nex->prev = pre;
            DestroyNode(cur);
        }
        cur = cur->next;
    }
    return;
}

void DLinklistDestroy(DLinkNode** phead)//销毁整个链表
{
    if(phead == NULL)
        return;
    DLinkNode* cur = (*phead)->next;
    while(cur != *phead)
    {
        DLinkNode* nex = cur->next;
        DestroyNode(cur);
        cur = nex;
    }
    DestroyNode(*phead);//要将头结点也销毁
    *phead = NULL;//置空,避免成为野指针
}

void TestInit()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    printf("excepted is 0,actual is %d\n",(int)head->data);//初始化中的0用%c打印不出来,这里用%d,且要进行强转为int,防止发生错误
}

void TestPushBack()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushBack(head,'a');
    DLinklistPushBack(head,'b');
    DLinklistPushBack(head,'c');
    DLinklistPushBack(head,'d');
    DLinklistPushBack(head,'e');
    DLinklistPrint(head,"尾插五个元素");
}

void TestPopBack()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushBack(head,'a');
    DLinklistPushBack(head,'b');
    DLinklistPushBack(head,'c');
    DLinklistPushBack(head,'d');
    DLinklistPrint(head,"尾插四个元素");
    DLinklistPopBack(head);
    DLinklistPopBack(head);
    DLinklistPrint(head,"尾删两个元素");
    DLinklistPopBack(head);
    DLinklistPopBack(head);
    DLinklistPrint(head,"再尾删两个元素");
}

void TestPushFront()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushFront(head,'a');
    DLinklistPushFront(head,'b');
    DLinklistPushFront(head,'c');
    DLinklistPushFront(head,'d');
    DLinklistPushFront(head,'e');
    DLinklistPrint(head,"头插五个元素");
}

void TestPopFront()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushFront(head,'a');
    DLinklistPushFront(head,'b');
    DLinklistPushFront(head,'c');
    DLinklistPushFront(head,'d');
    DLinklistPrint(head,"头插五个元素");
    DLinklistPopFront(head);
    DLinklistPopFront(head);
    DLinklistPrint(head,"头删两个元素");
    DLinklistPopFront(head);
    DLinklistPopFront(head);
    DLinklistPrint(head,"再头删两个元素");
}

void TestFind()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushFront(head,'a');
    DLinklistPushFront(head,'b');
    DLinklistPushFront(head,'c');
    DLinklistPushFront(head,'d');
    DLinklistPushFront(head,'e');
    DLinklistPrint(head,"头插五个元素");
    DLinkNode* ret = DLinklistFind(head,'c');
    printf("[%c|%p]\n",ret->data,ret);
    DLinkNode* ret1 = DLinklistFind(head,'h');
    if(ret1 == NULL)
        printf("没找到\n");
    else
        printf("[%c|%p]\n",ret1->data,ret1);
}

void TestInsert()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushBack(head,'a');
    DLinklistPushBack(head,'b');
    DLinklistPushBack(head,'c');
    DLinklistPushBack(head,'d');
    DLinklistPrint(head,"尾插五个元素");
    DLinkNode* pos = head->next;
    DLinklistInsertBefore(head,pos,'h');
    DLinklistPrint(head,"向a前插入h");
    pos = head;
    DLinklistInsertBefore(head,pos,'z');
    DLinklistPrint(head,"向head前插入z");
pos = head->prev;
    DLinklistInsertAfter(head,pos,'l');
    DLinklistPrint(head,"在最后一个结点之后插入l");
}

void TestErase()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushFront(head,'a');
    DLinklistPushFront(head,'b');
    DLinklistPushFront(head,'c');
    DLinklistPushFront(head,'d');
    DLinklistPrint(head,"头插五个元素");
    DLinkNode* pos = head;
    DLinklistErase(head,pos);
    DLinklistPrint(head,"删除head");
    pos = head->next->next;
    DLinklistErase(head,pos);
    DLinklistPrint(head,"删除c");
    pos = head->prev;
    DLinklistErase(head,pos);
    DLinklistPrint(head,"删除a");
}

void TestRemove()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushFront(head,'a');
    DLinklistPushFront(head,'b');
    DLinklistPushFront(head,'c');
    DLinklistPushFront(head,'d');
    DLinklistPrint(head,"头插五个元素");
    DLinklistRemove(head,0);
    DLinklistPrint(head,"删除0");
    DLinklistRemove(head,'a');
    DLinklistPrint(head,"删除a");
    DLinklistRemove(head,'d');
    DLinklistPrint(head,"删除d");
}

void TestRemoveAll()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushFront(head,'a');
    DLinklistPushFront(head,'a');
    DLinklistPushFront(head,'c');
DLinklistPushFront(head,'a');
    DLinklistPrint(head,"头插五个元素");
    DLinklistRemoveAll(head,'a');
    DLinklistPrint(head,"删除a");
}

void TestDestroy()
{
    SHOW_NAME;
    DLinkNode* head;
    DLinklistInit(&head);
    DLinklistPushFront(head,'a');
    DLinklistPushFront(head,'b');
    DLinklistPushFront(head,'c');
    DLinklistPushFront(head,'d');
    DLinklistPushFront(head,'e');
    DLinklistPrint(head,"头插五个元素");
    DLinklistDestroy(&head);
}

int main()
{
    TestInit();
    TestPushBack();
    TestPopBack();
    TestPushFront();
    TestPopFront();
    TestFind();
    TestInsert();
    TestErase();
    TestRemove();
    TestRemoveAll();
    TestDestroy();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lycorisradiata__/article/details/79808926