双向链表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了双向链表相关的知识,希望对你有一定的参考价值。

  • 意义:

    解决单链表的由于方向性引起的效率问题

    单链表有个缺陷,就是当数据量比较大的时候,当需要对已知节点做删除,排序的等操作时,有一个问题,就是当需要从头节点开始遍历,往往效率较低,

    head==>1 ==> 2 ==>3 ==>4==5

    当我需要删除3这个结点时,就得知道2这个结点的指针,但是只能从头指针开始遍历,才能知道

    双向链表的指针域,除了包含一个后继指针外还包括一个前驱指针,这样子,当拥有一个已知结点时,就不要从头遍历就可以知道这个指针的前驱指针,直接使用即可

     head<==> 1<==>2<==>3

    当已知3这个结点时,可以通过前驱指针,得到2这个结点的指针,然后可以做相应的处理

  • 2.实现

    2.1 数据结构

    typedef struct node
    {
        int data;                                           //数据域
        struct node *next;                                  //指针域
        struct node *prep;
    }NODE_t;

    next 为后继指针,prep为前驱指针

    2.2 创建

    NODE_t *CreatNodeList()
    {
        NODE_t *head = NULL;
    
        head = (NODE_t *)malloc(sizeof(NODE_t));
        if(!head)
            exit(-1);
            head->next = NULL; 
        head->prep = NULL;
    
        return head;
    }

    2.2 插入

    int InsertNode(NODE_t *head,int data)
    {
        NODE_t *cur = NULL;
    
        if(!head)
            exit(-1);
    
        cur = (NODE_t *)malloc(sizeof(NODE_t));
        if(!cur)
            exit(-1);
    
        cur->data = data;
        if(!head->next)
        {
            // 当只有头节点时
            cur->next = head->next;
            cur->prep = head;
            head->next = cur;
        }
        else
        {
            // 当链表有节点元素时
            cur->next = head->next;
            head->next->prep = cur;
            cur->prep = head;
            head->next = cur;
        }
    
        return 0;
    }

    2.3 查找

    NODE_t *findNode(NODE_t *head,int data)
    {
        head = head->next;
        while(head)
        {
            if(head->data == data)
            {
                break;
            }
            head = head->next;
        }
        if(head == NULL)
        {
            printf("sorry,%d is not in the list\n",data);
        }
    
        return head;
    }

    2.4 删除

    int DeleteNodeOfList(NODE_t *head,NODE_t *pfind)
    {
    
        if(pfind->next != NULL)
        {
            pfind->prep->next = pfind->next;
            pfind->next->prep = pfind->prep;
        }
        else
        {
            // 处理尾节点
            pfind->prep->next = NULL;
        }
    
        free(pfind);
        pfind = NULL;
    
        return 0;
    }

    2.5 修改

    int UpdateNode(NODE_t *head,int olddata,int newdata)
    {
        NODE_t *p = findNode(head,olddata);
        if(p)
        {
            p->data = newdata;
        }
    
        return 0;
    }
    

    2.6 排序

    int sortList(NODE_t *head)
    {
        int i = 0,j = 0;
        int listlen = 0;
        int tmpData = 0;
        NODE_t *p = NULL;
    
        // 使用冒泡排序,不动指针域,比较数据域,使用临时变量,将有大小之别的节点的数据域交换
        // 得到链表长度,方便冒泡
        listlen = ListNodeLen(head);
    
        // 指到首节点
        p = head->next;
        for(i = 0;i < listlen-1;i++)
        {
            // 每一轮从头开始
            p = head->next;
            for(j = 0;j<listlen - i-1;j++)
            {
                // 将小值排在前面
                if(p->data > p->next->data)
                {
                    tmpData = p->data;
                    p->data = p->next->data;
                    p->next->data = tmpData;
                }
                p = p->next;
            }
        }
    
        return 0;
    }

    以上是关于双向链表的主要内容,如果未能解决你的问题,请参考以下文章

    带头节点的双向链表

    《链表》之带头双向循环链表

    7L-双线链表实现

    代码模板实现双向链表的去重拼接合并排序

    数据结构之带头结点的循环双向链表详细图片+文字讲解

    双向链表 - 是啥导致我的代码引发编译器错误,我该如何解决?