C语言之双向链表(头结点与节点结构不相同)

双向链表主要注意:
1、插入节点要考虑到是在第1个节点和最后一个节点上,或者是中间,因情况不同处理的方法也不同
2、移除链表上的一个节点要考虑是1个节点还是最后一个节点上,或者是中间,因情况不同处理的方法也不同

头文件:

#ifndef __PLink2_H
#define __PLink2_H


typedef struct Node
{
    char    name[20];
    char    author[20];
    float   price;
    int     num;
    struct Node *prev;
    struct Node *Next;

}Node;

typedef struct Head
{
    int len;
    struct Node *Next;

}Head;

Head *CreateHead2();                                //创建一个头结点
int DestroyHead2(Head *head);                       //删除整条链表

Node *CreateNode2(Node *node);                      //申请节点内存空间(malloc)
int DestroyNode2(Node *node);                       //删除节点的内存
int InsertNodeAtHead2(Head *head, Node *NewNode);   //在链表中插入到第一个节点
int RemoveNode2(Head *head, Node *node);            //从链表中移除一个节点,但不删除内存
Node *SreachNode2(Head *head, char *name);          //搜索链表中的一个节点

int AddNode2(Head *head, Node *node);               //向链表追加一个节点
int InsertNode(Head *head, Node *node, int add);    //在链表指定位置上插入一个节点

int TwinLink();
int PrintfList2(Head *head);

#endif

源文件(.c):

#include "PLink2.h"

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

//创建头链表的内存空间
Head *CreateHead2()
{
    Head *New = NULL;

    New = (Head *)malloc(sizeof(Head) );
    if(New == NULL)
    {
        printf("Error malloc failed\n");
        return NULL;
    }
    memset(New, 0, sizeof(Head));
    New->Next = NULL;

    return New;
}

//删除整条链表的内存空间
int DestroyHead2(Head *head)
{
    Node *next = NULL;
    Node *node = NULL;

    if(head == NULL)
    {
        return -1;
    }

    node = head->Next;
    while(node != NULL)
    {
        next = node->Next;
        DestroyNode2(node);
        node = next;
    }
    free(head);
    head = NULL;

    return 0;
}

//创建申请节点内存空间(malloc)
Node *CreateNode2(Node *node)
{
    Node *pstNew = NULL;

    pstNew = (Node *)malloc(sizeof(Node) );
    if(pstNew == NULL)
    {
        printf("Error malloc failed\n");
        return NULL;
    }

    if(node != NULL)
    {
        memcpy(pstNew, node, sizeof(Node) );
        pstNew->prev = NULL;
        pstNew->Next = NULL;
    }
    else
    {
        memset(pstNew, 0, sizeof(Node));
    }

    return pstNew;
}

//删除节点内存空间
int DestroyNode2(Node *node)
{
    if(node == NULL) return -1;

    free(node);
    node = NULL;

    return 0;
}

//每次插入新节点都在第一个节点插入
int InsertNodeAtHead2(Head *head, Node *NewNode)
{
    Node *temp = NULL;

    if(head == NULL || NewNode ==NULL)
    {
        printf("InsertNodeAtHead is failed\n");
        return -1;
    }

    temp = head->Next;
    head->Next = NewNode;

    NewNode->Next = temp;
    NewNode->prev = NULL;
    if(temp != NULL)
    {
        temp->prev = NewNode;
    }

    head->len++;

    return 0;
}

//从链表中移除一个节点,但不删除内存
int RemoveNode2(Head *head, Node *node)
{
    Node *temp = NULL;

    if(head == NULL || node ==NULL) return -1;

    temp = head->Next;
    while(temp != NULL)
    {
        if(temp == node ) break;
        temp = temp->Next;
    }

    if(temp == NULL) return -1; //空链表

    if(temp->prev != NULL)      //不是第一个节点
    {
        temp->prev->Next = temp->Next;
    }
    else    //第一个节点
    {
        head->Next = temp->Next;
    }

    if(temp->Next != NULL)      //不是最后节点
    {
        temp->Next->prev = temp->prev;
    }
    temp->prev = NULL;
    temp->Next = NULL;
    head->len--;

    return 0;
}

//搜索链表中的一个节点
Node *SreachNode2(Head *head, char *name)
{
    Node *node = NULL;

    if(head == NULL || name ==NULL) return NULL;

    node = head->Next;
    while(node != NULL)
    {
//        if(node->name == name) //非字符串比较
        if(strcmp(node->name, name) == 0 )
        {
            break;
        }
        node = node->Next;
    }

    return node;
}

//在双向链表末尾追加一个节点
int AddNode2(Head *head, Node *node)
{
    Node *last = NULL;
    Node *temp = NULL;

    if(head == NULL || head == NULL)    return -1;

    temp = head->Next;
    if(temp == NULL)
    {
        head->Next = node;
        node->prev = NULL;
        node->Next = NULL;
    }
    else
    {
        while(temp != NULL)   //最后一个节点时,跳出循环
        {
            last = temp;
            temp = temp->Next;
        }
        node->prev = last;
        last->Next = node;
        node->Next = NULL;
    }
    head->len++;

    return 0;
}

//在链表指定位置上插入一个节点
int InsertNode(Head *head, Node *node, int add)
{
    Node *temp = NULL;

    if(head == NULL || head == NULL || add <= 0)     return -1;

    if(add == 1)
    {
        InsertNodeAtHead2(head, node);
    }
    else
    {
        temp = head->Next;
        while(temp != NULL)
        {
            if(add == 1)
            {
               break;
            }
            add--;
            temp = temp->Next;
        }

        if( (temp != NULL) && (add == 1) )  //插入到链表中某个节点上(2-链表最后一个)
        {
            node->Next = temp->prev->Next;
            temp->prev->Next = node;
            node->prev = temp->prev;
            temp->prev = node;
        }
        else if( (temp == NULL) && (add == 1) ) //向链表追加一个节点
        {
            AddNode2(head, node);
        }
        else if( (temp == NULL) && (add > 1) )  //超出了插入节点的范围
        {
            return -1;
        }
    }
    head->len++;

    return 0;
}

测试代码:

//填写节点数据
int NodeData(Node *node, char *name, char *author, float price, int num)
{
    if(node == NULL) return -1;

    strcpy(node->name, name);
    strcpy(node->author, author);
    node->price = price;
    node->num = num;

    return 0;
}

//打印链表
int PrintfList2(Head *head)
{
    Node *p = head->Next;

    if(head == NULL) return -1;

    while(p != NULL)
    {
        printf("%s\n", p->name);
        p = p->Next;
    }
    printf("\n");

    return 0;
}

//测试个函数功能
int TwinLink()
{
    Head *head = (Head *)CreateHead2();
    Node *Newnode = NULL;
    Node node;

    NodeData(&node, "aaa", "zhangsan", 100.05, 5);  //填写链表的数据
    Newnode = CreateNode2(&node);                   //创建一个节点并将填写的数据写入节点中
    AddNode2(head, Newnode);                        //向链表追加一个节点
    PrintfList2(head);                              //打印链表的数据

    NodeData(&node, "bbb", "lisi", 55.44, 56);
    Newnode = CreateNode2(&node);
    InsertNodeAtHead2(head, Newnode);               //插入一个节点到链表的第1个节点的位置上
    PrintfList2(head);

    NodeData(&node, "ccc", "wangwu", 22.05, 9);
    Newnode = CreateNode2(&node);
    InsertNode(head, Newnode, 2);                   //向链表插入一个节点到第2个节点的位置上
    PrintfList2(head);

    Newnode = SreachNode2(head, "ccc");             //在链表上搜索一个节点
    RemoveNode2(head, Newnode);                     //在链表上移除一个节点
    DestroyNode2(Newnode);                          //删除这个节点的内存
    PrintfList2(head);

    return 0;
}

测试效果图:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值