双链表

什么是双向链表

我们知道单向链表中有一个结点指针指向下一个结点,那么双向链表,顾名思义,双向链表有两个结点指针,一个指向前一个结点,一个指下一个结点。

双向链表的优点

相对于单向链表的优点,双向链表不仅可以访问下一个结点,还可以访问下一个结点,可以更灵活的做一些复杂的处理。

双向链表的实现

实验代码
double_linklist.h

#ifndef _DOUBLE_LINKLIST_H_
#define _DOUBLE_LINKLIST_H_



#include <stdbool.h>


/* 双向链表结构 */
struct node
{
    int data;
    struct node* pPre;
    struct node* pNext;
};



/*
 * 函数名称:creat_node
 * 函数功能:创建结点
 * 返 回 值:结点指针
 */
 struct node* creat_node(void);



/*
 * 函数名称:insert_node_from_tail
 * 函数功能:从尾部插入结点
 * 输入参数:pHead-链表头指针,data-需要插入的结点的数据
 * 返 回 值:true-成功,false-失败
 */
bool insert_node_from_tail(struct node* pHead, int data);




/*
 * 函数名称:insert_node_from_head
 * 函数功能:从头部插入结点
 * 输入参数:pHead-链表头指针,data-需要插入的结点的数据
 * 返 回 值:true-成功,false-失败
 */
bool insert_node_from_head(struct node* pHead, int data);





/*
 * 函数名称:insert_node_to_specifiled_location
 * 函数功能:插入到指定位置
 * 输入参数:pHead-链表头指针,data-需要插入的结点的数据
 * 返 回 值:true-成功,false-失败
 */
bool insert_node_to_specifiled_location(struct node* pHead, int data, int location);





/*
 * 函数名称:remove_node
 * 函数功能:移除结点
 * 输入参数:pHead-链表头指针,data-需要插入的结点的数据
 * 返 回 值:true-成功,false-失败
 */
bool remove_node(struct node* pHead, int data);





/*
 * 函数名称:destory_linklist
 * 函数功能:销毁链表
 * 输入参数:pHead-链表头指针
 * 返 回 值:true-成功,false-失败
 */
void destory_linklist(struct node* pHead);



/* 
 * 函数名称:linklist_print
 * 函数功能:遍历钟表
 * 输入参数:pHead - 链表头指针
 */
 void linklist_print(struct node* pHead);



#endif

double_linklist.c

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


/*
 * 函数名称:creat_node
 * 函数功能:创建结点
 * 返 回 值:结点指针
 */
 struct node* creat_node(void)
 {
     struct node* pTmp = (struct node*)malloc(sizeof(struct node));
     if(pTmp == NULL)
        return NULL;

     pTmp->data = 0;
     pTmp->pPre = NULL;
     pTmp->pNext = NULL;
 }



/*
 * 函数名称:insert_node_from_tail
 * 函数功能:从尾部插入结点
 * 输入参数:pHead-链表头指针,data-需要插入的结点的数据
 * 返 回 值:true-成功,false-失败
 */
bool insert_node_from_tail(struct node* pHead, int data)
{
    struct node* pTmp = pHead;

    while(pTmp->pNext != NULL)
    {
        pTmp = pTmp->pNext;
    }

    struct node* pAdd = creat_node();
    if(pAdd == NULL)
        return false;

    pAdd->data = data;
    pAdd->pPre = pTmp;
    pAdd->pNext = NULL;

    pTmp->pNext = pAdd; 

    return true;
}




/*
 * 函数名称:insert_node_from_head
 * 函数功能:从头部插入结点
 * 输入参数:pHead-链表头指针,data-需要插入的结点的数据
 * 返 回 值:true-成功,false-失败
 */
bool insert_node_from_head(struct node* pHead, int data)
{
    struct node* pAdd = creat_node();
    if(pAdd == NULL)
        return NULL;

    pAdd->data = data;
    pAdd->pPre = pHead;
    pAdd->pNext = pHead->pNext;

    pHead->pNext = pAdd;

    return true;
}




/*
 * 函数名称:insert_node_to_specifiled_location
 * 函数功能:插入到指定位置
 * 输入参数:pHead-链表头指针,data-需要插入的结点的数据
 * 返 回 值:true-成功,false-失败
 */
bool insert_node_to_specifiled_location(struct node* pHead, int data, int location)
{
    struct node*pTmp = pHead->pNext;

    struct node* pAdd = creat_node();
    if(pAdd == NULL)
        return false;

    int i;
    for(i=0; i<location; i++)
    {
        if(pTmp->pNext == NULL)
            return false;

        pTmp = pTmp->pNext;
    }

    pAdd->data = data;
    pAdd->pNext = pTmp;
    pAdd->pPre = pTmp->pPre;
    pTmp->pPre->pNext = pAdd;

    return false;
}





/*
 * 函数名称:remove_node
 * 函数功能:移除结点
 * 输入参数:pHead-链表头指针,data-需要插入的结点的数据
 * 返 回 值:true-成功,false-失败
 */
bool remove_node(struct node* pHead, int data)
{
    struct node* pTmp = pHead->pNext;

    struct node* pDel = creat_node();
    if(pDel == NULL)
        return false;

    int del_couts = 0;

    while(pTmp != NULL)
    {
        if(pTmp->data == data)
        {
            pDel = pTmp;

            pDel->pPre->pNext = pDel->pNext;
            free(pDel);

            del_couts++;
        }

        pTmp = pTmp->pNext;
    }

    if(del_couts != 0)
        return true;
        
    return false;
}





/*
 * 函数名称:destory_linklist
 * 函数功能:销毁链表
 * 输入参数:pHead-链表头指针
 * 返 回 值:true-成功,false-失败
 */
void destory_linklist(struct node* pHead)
{
    struct node* pTmp = NULL;

    while( pHead != NULL)
    {
        pTmp = pHead;
        free(pTmp);
        pTmp = NULL;

        pTmp = pTmp->pNext;
    }

}





/* 
 * 函数名称:linklist_print
 * 函数功能:遍历钟表
 * 输入参数:pHead - 链表头指针
 */
 void linklist_print(struct node* pHead)
 {
     printf("linklist: ");
     pHead = pHead->pNext;

     while(pHead != NULL)
     {
         printf("%d ", pHead->data);
         pHead = pHead->pNext;
     }

     printf("\r\n");
 }

main.c

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


int main(void)
{
    struct node* pHeader = creat_node();
    if(pHeader == NULL)
    {
        return -1;
    }

    int i;

    /* 尾插入从1到10 */
    for(i=0; i<10; i++)
        insert_node_from_tail(pHeader, i+1);
    
    printf("尾部插入从 1 到 10\n");
    linklist_print(pHeader);

    /* 在第3个位置插入5 */
    insert_node_to_specifiled_location(pHeader, 5, 3);

    printf("在第3个位置插入5\n");
    linklist_print(pHeader);

    /* 头部插入10 */
    insert_node_from_head(pHeader, 10);
    printf("在头部插入10\n");
    linklist_print(pHeader);

    /* 移除数据为5的结点 */
    remove_node(pHeader, 5);

    printf("移除数据为5的结点\n");
    linklist_print(pHeader);

    remove_node(pHeader, 8);

    printf("移除数据为8的结点\n");
    linklist_print(pHeader);

    destory_linklist(pHeader);

    return 0;
}

运行结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lzg2021

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值