数据结构——双向链表

双向链表的结构:

在这里插入图片描述

双向链表由链表对象,头结点,中间结点以及尾结点组成每一部分结点结构或是指针内容存在差异,需要牢记双向链表的结构,双向链表的结构使我们能够通过一个中间节点找到它前后的结点,这是与单向链表的最大区别。

需要熟练掌握的基本操作:

在这里插入图片描述

让我们在记牢理解双向链表的结构以后直接上代码练习

封装双向链表:1:头文件定义双向链表的结构

#ifndef __DOULINK_H__
#define __DOULINK_H__
//双向链表存储的数据类型
typedef struct stu
{
    int id;
    char name[32];
    int score;
}Data_type_t;

/*双向链表的结点类型*/
typedef struct dounode
{
    Data_type_t data;
    struct dounode *ppre;  //指向前驱结点的指针
    struct dounode *pnext; //指向后继结点的指针
}DNode_t;

/*双向链表对象类型*/
typedef struct doulink
{
    DNode_t *phead;   //双向链表头结点地址
    int clen;         //双向链表结点个数
}DLink_t;
extern DLink_t *create_doulink();
extern int insert_doulink_head(DLink_t *pdlink, Data_type_t data);
extern int is_empty_doulink(DLink_t *pdlink);
extern void doulink_for_each(DLink_t *pdlink, int dir);
extern int insert_doulink_tail(DLink_t *pdlink, Data_type_t data);
extern int delete_doulink_head(DLink_t *pdlink);
extern int delete_doulink_tail(DLink_t *pdlink);

使用头插法构建双向链表:头插法是重点

#include "doulink.h"
#include <stdio.h>
#include <stdlib.h>


DLink_t *create_doulink()
{
    DLink_t *pdlink= malloc(sizeof(DLink_t));
    if (NULL == pdlink)
    {
        printf("malloc error");
        return NULL;
    }
    pdlink->phead = NULL;
    pdlink->clen = 0;

    return pdlink;
}

int is_empty_doulink(DLink_t *pdlink)
{
    return NULL == pdlink->phead;

}


int insert_doulink_head(DLink_t *pdlink, Data_type_t data)
{
    DNode_t *pnode = malloc(sizeof(DNode_t));
    if (NULL == pnode)
    {
        printf("malloc error");
        return -1;
    }
    pnode->data = data;
    pnode->ppre = NULL;
    pnode->pnext = NULL;

    if (is_empty_doulink(pdlink))
    {
        pdlink->phead = pnode;
    }
    else
    {
        pnode->pnext = pdlink->phead;
        pdlink->phead->ppre = pnode;
        pdlink->phead = pnode;
    }
    pdlink->clen++;

    return 0;
}

主函数部分:

#include <stdio.h>
#include "doulink.h"

int main(void)
{

    Data_type_t stus[5] = {{1, "zhangsan", 99},
                            {2, "lisi", 100}, {3, "wangwu", 90}, 
                            {4, "maliu", 56}, {5, "tianqi", 66}};

    DLink_t *pdlink = create_doulink();
    if (NULL == pdlink)
    {
        return -1;
    }

    insert_doulink_head(pdlink, stus[0]);
    insert_doulink_head(pdlink, stus[1]);
    insert_doulink_head(pdlink, stus[2]);
    insert_doulink_tail(pdlink, stus[3]);
    insert_doulink_tail(pdlink, stus[4]);


构建好双向链表后,对于双向链表的各种基本操作:

遍历打印:dir1顺序打印,direlse逆序打印

void doulink_for_each(DLink_t *pdlink, int dir)
{
    if (is_empty_doulink(pdlink))
    {
        return ;
    }
    DNode_t *ptmp = pdlink->phead;
    if (dir)
    {
        while (ptmp != NULL)
        {
            printf("%d %s %d\n", ptmp->data.id, ptmp->data.name, ptmp->data.score);
            ptmp = ptmp->pnext;
        }
    }
    else
    {
        while (ptmp->pnext != NULL)
        {
            ptmp = ptmp->pnext;
        }
        while (ptmp != NULL)
        {
             printf("%d %s %d\n", ptmp->data.id, ptmp->data.name, ptmp->data.score);
             ptmp = ptmp->ppre;
        }
    }
    printf("\n");
}

尾插法

int insert_doulink_tail(DLink_t *pdlink, Data_type_t data)
{
    DNode_t *pnode = malloc(sizeof(DNode_t));
    if (NULL == pnode)
    {
        printf("malloc error\n");
        return -1;
    }
    pnode->data = data;
    pnode->ppre = NULL;
    pnode->pnext = NULL;

    if (is_empty_doulink(pdlink)) //空链表情况
    {
        pdlink->phead = pnode;
    }
    else //非空链表情况
    {
        DNode_t *ptmp = pdlink->phead;
        while (ptmp->pnext != NULL)
        {
            ptmp = ptmp->pnext;
        }
        ptmp->pnext = pnode;
        pnode->ppre = ptmp;
    }
    pdlink->clen++;

    return 0;
}

删除头结点:

int delete_doulink_head(DLink_t *pdlink)
{
    if (is_empty_doulink(pdlink))
    {
        return -1;
    }

    DNode_t *pdel = pdlink->phead;
    pdlink->phead = pdel->pnext;
    if (pdlink->phead != NULL)
    {
        pdlink->phead->ppre = NULL;
    }
    free(pdel);
    pdlink->clen--;

    return 0;
}

删除尾结点:

int delete_doulink_tail(DLink_t *pdlink)
{
    if (is_empty_doulink(pdlink))
    {
        return -1;
    }

    DNode_t *ptmp = pdlink->phead;
    if (1 == pdlink->clen)
    {
        free(ptmp);
        pdlink->phead = NULL;
    }
    else
    {
        while (ptmp->pnext != NULL)
        {
            ptmp = ptmp->pnext;
        }
        ptmp->ppre->pnext = NULL;
        free(ptmp);
    }
    pdlink->clen--;

    return 0;
}

销毁链表

int destory_dblink(dbLINK_T *plink)
{
    if(is_empty_doubleLink(plink))
    {
        printf("空结点");
        return -1;
    }

    dbNODE_T *p=plink->phead;
    while(p!=NULL)
    {
        p=p->pnext;
        head_node_delet(plink);
        
    }
    free(plink);
    return 0;
    

}

查找结点并返回其地址

dbNODE_T *findnode(dbLINK_T *plink,char name[20])
{
    if(is_empty_doubleLink(plink))
    {
        printf("空链表,无结点可查");
        return NULL;
    }
    dbNODE_T *p=plink->phead;
    while (p!=NULL)
    {
        if(strcmp(p->data.name,name)==0)
        {
            return p;
        }
        p=p->pnext;
    }
    printf("查找不到该学生");    
    return NULL;
}

根据名字修改学生分数

int findnodeAndChangeScore(dbLINK_T *plink,char name[20],int newscore)
{
    if(is_empty_doubleLink(plink))
    {
        printf("空链表,无结点可查");
        return -1;
    }
    dbNODE_T *p=plink->phead;
    while (p!=NULL)
    {
        if(strcmp(p->data.name,name)==0)
        {
            p->data.score=newscore;
            return 0;
        }
        p=p->pnext;
    }
    printf("查找不到该学生");    
    return -1;
}

查找结点并删除该结点:

int findnodeAndDELETnode(dbLINK_T *plink, char name[20])
{
    if(is_empty_doubleLink(plink))
    {
        printf("空链表,无结点可查\n");
        return -1;
    }
    
    dbNODE_T *p = plink->phead;
    
    // 遍历整个链表查找节点
    while (p != NULL)
    {
        if(strcmp(p->data.name, name) == 0)
        {
            // 情况1:删除头节点
            if(p->ppre == NULL)
            {
                head_node_delet(plink);
            }
            // 情况2:删除尾节点
            else if(p->pnext == NULL)
            {
                p->ppre->pnext = NULL;
                free(p);
                plink->clen--;
            }
            // 情况3:删除中间节点
            else
            {
                p->ppre->pnext = p->pnext;
                p->pnext->ppre = p->ppre;
                free(p);
                plink->clen--;
            }
            printf("找到并删除该学生节点\n");
            return 0;
        }
        p = p->pnext;
    }
    
    // 遍历完未找到节点
    printf("无法找到该同学,无法删除结点\n");
    return -1;
}

主函数

#include<stdio.h>
#include"doublelink.h"
int main(void)
{
    STUDENT_T stus[5]={{1,"zhangsan",99}
    ,{2,"lisi",100}
    ,{3,"wangwu",90}
    ,{4,"maliu",56}
    ,{5,"tianqi",66}};
    dbLINK_T *plink=creatlink(plink);
    if(plink==NULL)
    {
        printf("mallol error");
        return -1;
    }
    creat_db_NODE(plink,stus[0]);
    creat_db_NODE(plink,stus[1]);
    creat_db_NODE(plink,stus[2]);
    creat_db_NODE(plink,stus[3]);
    creat_db_NODE(plink,stus[4]);
  /*  insert_dblink_tail(plink,stus[4]);
    leach_dblink(plink,1);
    head_node_delet(plink);
    deletLink_fromTheLastNODE(plink);*/
    leach_dblink(plink,1);
  /*  dbNODE_T *ret=findnode(plink,"wangwu");
    if(ret==NULL)
    {
        return -1;
    }
    printf("学生名:%p\n",ret);*/
  /*  findnodeAndChangeScore(plink,"lisi",50);
    leach_dblink(plink,1);*/
    findnodeAndDELETnode(plink,"wangwu");
    leach_dblink(plink,1);
    destory_dblink(plink);
  //  leach_dblink(plink,0);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值