首页 > 其他 > 详细

双向链表

时间:2021-04-29 14:51:32      阅读:17      评论:0      收藏:0      [点我收藏+]

一.双向链表

头结点的前驱指向NULL,后结点的后继指向NULL

二.双向链表的设计

1.双向链表的操作

typedef int ELEMTYPE;

typedef struct DNode
{
    ELEMTYPE data;//数据域
    DNode* next;//指向直接后继
    DNode* prior;//指向直接前驱
}DNode, * Dlist;//Dlist == DNode*


//初始化
void Initlist(Dlist plist);

//头插
bool Insert_head(Dlist plist, ELEMTYPE val);

//尾插
bool Insert_tail(Dlist plist, ELEMTYPE val);

//按位置pos插入
bool Insert_pos(Dlist plist, int pos, ELEMTYPE val);

//判空
bool IsEmpty(Dlist plist);

//获取链表有效节点个数
int GetLength(Dlist plist);

//查找第一个值是key的节点,找到的话返回这个节点,没找到的话返回NULL
DNode* Search(Dlist plist, ELEMTYPE key);

//删除位置pos
bool Delpos(Dlist plist, int pos);

//删除第一个值为key的节点
bool Delval(Dlist plist, ELEMTYPE key);

//尾删
bool Del_tail(Dlist plist);

//头删
bool Del_head(Dlist plist);

//找节点的前驱
DNode* Getprior(Dlist plist, ELEMTYPE val);

//找节点的后继
DNode* Getnext(Dlist plist, ELEMTYPE val);

//清空, 直接调用销毁
void Clear(Dlist plist);

//销毁
void Destroy(Dlist plist);

//打印
void Show(Dlist plist);

2.双向链表的实现

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>// #include <malloc.h>
#include "dlist.h"


//define 0 ((void*)0)
//nullptr     NULL        nullptr

//初始化
void Initlist(Dlist plist)
{
    //断言
    assert(plist != NULL);//nullptr
    if (plist == NULL)
        return;

    //赋值为我们给的初始值
    //plist->data; 数据域不需要赋值
    plist->next = NULL;
    plist->prior = NULL;
}

static DNode* BuyNode(ELEMTYPE val)
{
    DNode* pnewnode = (DNode*)malloc(sizeof(DNode));
    if (pnewnode == NULL)
        return false;
    pnewnode->data = val;
    pnewnode->next = NULL;
    pnewnode->prior = NULL;

    return pnewnode;
}
//头插
bool Insert_head(Dlist plist, ELEMTYPE val)
{
    //断言

    //创建一个新节点
    //DNode * pnewnode = BuyNode(val);
    DNode* pnewnode = (DNode*)malloc(sizeof(DNode));
    if (pnewnode == NULL)
        return false;
    pnewnode->data = val;
    pnewnode->next = NULL;
    pnewnode->prior = NULL;

    //插入
    pnewnode->next = plist->next;//永远第一步  先让新节点把下一个节点绑住  //结点
    pnewnode->prior = plist;

    //特殊:两种情况  一种有节点存在, 一个光杆司令
    if (plist->next != NULL)
    {
        plist->next->prior = pnewnode;// -> = (*).
    }

    plist->next = pnewnode;
    return true;
}

//尾插
bool Insert_tail(Dlist plist, ELEMTYPE val)
{
    //assert
    //创建新节点
    DNode* pnewnode = (DNode*)malloc(sizeof(DNode));
    pnewnode->data = val;

    //找到前驱

    DNode* p;
    for (p = plist; p->next != NULL; p = p->next);

    //插入

    pnewnode->next = NULL;
    pnewnode->prior = p;

    p->next = pnewnode;
    return true;
}


//按位置pos插入
bool Insert_pos(Dlist plist, int pos, ELEMTYPE val)
{
    //断言
    assert(plist != NULL && pos >= 0 && pos <= GetLength(plist));
    if (plist == NULL || pos<0 || pos>GetLength(plist))
        return false;

    //创建新节点
    DNode* pnewnode = (DNode*)malloc(sizeof(DNode));
    pnewnode->data = val;
    //找到插入的位置pos
    DNode* p = plist;
    for (int i = 0; i < pos; i++)
    {
        p = p->next;
    }
    //for(p=plist,int i=0; i<pos; i++,p=p->next);
    //插入
    pnewnode->next = p->next;
    pnewnode->prior = p;
    if (p->next != NULL)
    {
        p->next->prior = pnewnode;
    }
    p->next = pnewnode;
    return true;
}

//判空
bool IsEmpty(Dlist plist)
{
    return plist->next == NULL;
}

//获取链表有效节点个数
int GetLength(Dlist plist)
{
    int count = 0;
    for (DNode* p = plist->next; p != NULL; p = p->next)
    {
        count++;
    }

    return count;
}

//查找第一个值是key的节点,找到的话返回这个节点,没找到的话返回NULL
DNode* Search(Dlist plist, ELEMTYPE key)
{
    //assert
    //遍历找值为key的第一个节点

    for (DNode* p = plist->next; p != NULL; p = p->next)
    {
        if (p->data == key)
        {
            return p;
        }
    }

    return NULL;
}

//删除位置pos
bool Delpos(Dlist plist, int pos)
{
    //assert
    assert(plist != NULL && pos >= 0 && pos < GetLength(plist));
    if (plist == NULL || pos < 0 || pos >= GetLength(plist))
        return false;
    //找到删除的位置
    DNode* p = plist;
    for (int i = 0; i <= pos; i++)
    {
        p = p->next;
    }
    //删除节点
    p->prior->next = p->next;
    if (p->next != NULL)
    {
        p->next->prior = p->prior;
    }
    //释放空间
    free(p);
    p = NULL;

    return true;
}

//删除第一个值为key的节点
bool Delval(Dlist plist, ELEMTYPE key)
{
    //断言
    if (plist == NULL)
        return false;

    //找到位置pos的节点
    DNode* p = Search(plist, key);
    if (p == NULL)
    {
        return false;
    }

    //删除
    p->prior->next = p->next;
    if (p->next != NULL)
    {
        p->next->prior = p->prior;
    }

    //释放空间
    free(p);
    p = NULL;
    return true;
}


//尾删
bool Del_tail(Dlist plist)
{
    //断言
    if (plist == NULL)
        return false;
    //找删除的节点
    DNode* p;
    for (p = plist; p->next != NULL; p = p->next);

    //删除
    p->prior->next = NULL;

    //释放内存
    free(p);
    p = NULL;
    return true;
}

//头删
bool Del_head(Dlist plist)
{
    //assert
    if (plist == NULL || plist->next == NULL)
        return false;

    //找到位置
    DNode* p = plist->next;

    //删除
    plist->next = p->next;
    if (p->next != NULL)
    {
        p->next->prior = plist;
    }

    //释放内存
    free(p);
    p = NULL;

    return true;

}

//找节点的前驱
DNode* Getprior(Dlist plist, ELEMTYPE val)
{
    //assert
    DNode* p = Search(plist, val);
    /*if(p == NULL)
    {
        return NULL;
    }
    return p->prior;*/
    return p == NULL ? NULL : p->prior;

}

//找节点的后继
DNode* Getnext(Dlist plist, ELEMTYPE val)
{
    DNode* p = Search(plist, val);
    return p == NULL ? NULL : p->next;
}

//清空, 直接调用销毁
void Clear(Dlist plist)
{
    Destroy(plist);
}

//销毁
void Destroy(Dlist plist)
{
    //assert
    if (plist == NULL || plist->next == NULL)
        return;
    DNode* p = plist->next;

    while (plist->next != NULL)
    {
        p = plist->next;
        plist->next = p->next;
        free(p);
    }
}

//void Destroy1(Dlist plist)
//{
//    if(plist == NULL ||plist->next == NULL)
//        return;
//    DNode *p = plist->next;
//    DNode *q;
//    while(p != NULL)
//    {
//        q = p->next;
//        free(p);
//        p = q;
//    }
//
//    plist->next = NULL;
//}

//打印
void Show(Dlist plist)
{
    for (DNode* p = plist->next; p != NULL; p = p->next)
    {
        printf("%d ", p->data);
    }
    printf("\n");
}

3.双向链表的两种for循环

for (p = plist; p->next != NULL; p = p->next);

删除,插入操作时用

for (DNode* p = plist->next; p != NULL; p = p->next)

遍历时用

4.注意:

           1)头插时,需要判断头结点后是否有结点、

           2)按位置删除时,需要判断删除的点是否是最后一个结点

           3)连续解引用时,注意是否出现越界

 

双向链表

原文:https://www.cnblogs.com/xpei-1124/p/14717407.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!