双向循环链表

2023-05-11,,

循环双向链表如下图所示:

 大家通过图来看与循环单链表基本是一样,代码的套路也基本一样,除了每个节点都多一个前驱。
 很多和我一样的初学者都很困惑,单链表,双链表,还有循环链表为什么搞那么复杂,很简单因为需求。
 学编程你不得不时刻容纳新知识,很多人没有去深入去学习,就像没有驱动一样。有单向就有双向,有双向就有循环,更多的需求让大家进步,就像人不懂得满足。
 有些人问我,为什么别人能够把代码逻辑写的清晰,为什么如何别人能够那么优秀,很多人说:练习的多,敲代码量大,不得不否认确实有这方面因素,但是我认为思考更为重要。大量的思考让这些编程员中脑子可以浮动出任何的算法与数据结构,这也许才是真正的灵魂。
 扯远了,再来一张构造双向链表的图,因为与单链表不同,所以格外做了一张图让刚学习的朋友们删除等参考,分享更多的知识。

代码如下:

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

typedef struct Node
{
    int data;
    struct Node *next;
    struct Node *prior;
}Node,*PNode;

void ControlLinkList(PNode PHead);                      //控制函数
PNode CreateLinkList(void);                             //构造双向循环链表
int PositionLinkList(PNode PHead);                      //正向遍历
void ReverseLinkList(PNode PHead);                      //逆向遍历
void InsertLinkList(PNode PHead, int pos, int len);     //插入某节点
void DeleteLinkList(PNode PHead, int pos);              //删除某节点
void FindDLinkList(PNode PHead, int pos);               //查询某节点
void ReleaseLinkList(PNode PHead);                      //释放链表
void ReversesLinkList(PNode PHaed);                     //反转链表--对于循环双向链表反转没有太大意义

int main(void)
{

    PNode PHead = CreateLinkList();
    ControlLinkList(PHead);
    return 0;
}

PNode CreateLinkList(void)
{
    int len = 0;
    int i;
    PNode PHead = (PNode)malloc(sizeof(Node));
    PNode r;
    if( NULL == PHead )
    {
        printf("分配内存失败\n");
        exit(EXIT_FAILURE);
    }
    //初始化头
    PHead->data = 0;
    PHead->prior = PHead;
    PHead->next = PHead;
    r = PHead;

    printf("请输入构造几个节点: ");
    scanf("%d",&len);

    for( i = 0; i < len; i++ )
    {
        PNode p = (PNode)malloc(sizeof(Node));
        if( NULL == p )
        {
            printf("分配内存失败\n");
            exit(EXIT_FAILURE);
        }

        printf("Please input of data: ");
        scanf("%d",&p->data);

        p->next = NULL;                             //后驱为NULL
        p->prior = r;                               //前驱指向r也就是PHead头节点
        r->next = p;                                //然后r的后驱也就PHead的后驱指向p
        r = p;                                      //最后r = p;
    }
    r->next = PHead;
    PHead->prior = r;                               //这两步完成了链表循环,头尾想指
    return PHead;                                   //循环双向链表返回头指针既可以正向反向遍历
}

int PositionLinkList(PNode PHead)
{
    int i = 0;
    PNode p = PHead->next;                          //PHead->next才是链表第一个元素
    while( NULL != p && PHead != p )
    {
        i++;
        printf("No.%d of Data = %d\n",i,p->data);
        p = p->next;
    }
    printf("正向遍历成功");
    return i;
}

void ReverseLinkList(PNode PHead)
{
    int i = 0;
    PNode p = PHead->prior;                         //指向了链表尾部r
    while( NULL != p && p != PHead )
    {
        i++;
        printf("No.%d of Data = %d\n",i,p->data);
        p = p->prior;
    }
    printf("逆向遍历成功\n");
}

void InsertLinkList(PNode PHead, int pos, int data)
{
    int i = 1;
    PNode p = PHead->next;
    PNode PNew = (PNode)malloc(sizeof(Node));
    if( NULL == p )
    {
        printf("内存分配失败\n");
        exit(EXIT_FAILURE);
    }

    while( p != NULL && i != pos-1 )
    {
        i++;
        p = p->next;
    }

    PNew->data = data;
    p->next->prior = PNew;
    PNew->next = p->next;
    p->next = PNew;
    PNew->prior = p;

    printf("插入成功\n");
}

void FindLinkList(PNode PHead, int pos)
{
    PNode p = PHead->next;
    int i = 1;
    while( NULL !=p && i != pos )
    {
        i++;
        p = p->next; 
    }
    printf("No.%d of Data = %d\n", i, p->data);
}

void DeleteLinkList(PNode PHead, int pos)
{
    int i = 1;
    PNode p = PHead->next;
    PNode temp;
    while( NULL !=p && i != pos )
    {
        i++;
        p = p->next;
    }

    temp = p->next;                     //temp指向删除的节点
    p->next = p->next->next;            //p->next节点指向删除节点的next
    p->next->next->prior = p;   
    free(temp);
    printf("删除节点成功\n");
}

void ReleaseLinkList(PNode PHead)
{
    PNode p,q;
    p = PHead;
    q = p->next;
    while( q != PHead )
    {
        p = q;
        q = p->next;
        free(p);
    }
    free(PHead);
    printf("释放内存成功");
}

void ControlLinkList(PNode PHead)
{
    int len = 0;
    int pos = 0;
    len = PositionLinkList(PHead);
    ReverseLinkList(PHead);
    printf("请输入pos节点:  ");
    scanf("%d",&pos);
    InsertLinkList(PHead, pos, 10);
    PositionLinkList(PHead);
    printf("请输入查询的节点:  ");
    scanf("%d",&pos);
    FindLinkList(PHead, pos);
    printf("请输入删除的节点:  ");
    scanf("%d",&pos);
    DeleteLinkList(PHead, pos);
    PositionLinkList(PHead);
    ReleaseLinkList(PHead);
}

《双向循环链表.doc》

下载本文的Word格式文档,以方便收藏与打印。