通用式双向链表

本文详细介绍了通用式链表的结构设计,包括节点、表结构以及如何处理不同类型的数据。文章涵盖了节点的动态分配、释放、链表初始化、清空、销毁,以及增删查等操作的实现过程。
摘要由CSDN通过智能技术生成

首先设计链表的结点结构体,表结构体和测试用学生结构体。普通链表只能存放单一数据类型,而通用式链表可以存放各种数据类型,因此节点的data域设置为void,输出时强转为我们需要的数据类型。这里以存放student类型数据举例。

ELEMSIZE大小为四字节,如果存放的数据大于四字节则存放在data中,如果大于四字节则另外开辟一块空间,让data指向此空间。

1.购买节点

使用malloc开辟一块空间用于存放数据并memset设置初始值为0.

2.释放节点

3.购买节点

如果传入的elemsize大于四字节则开辟新空间,大小为sizeof(char)*elemsize,并设置初始值为0.

.

4.释放节点

这里释放的是存放数据大于四字节新开辟的空间。

5.初始化链表

购买节点并设置prev,next指向及各项赋初始值。

6.清空链表

当链表非空,则删除最后一个元素,直至删完。

7.摧毁链表

清空链表并释放节点

8.获取链表长度

链表不为空时返回plist的元素个数。

9.判空

判断链表中元素个数是否为0,满足则返回。

10.在元素p前插入pval

首先购买节点并设置指针指向,如果插入的pval字节不大于4,就将pval的值拷贝给s的data域。如果pval字节大于四字节则用上边写的buyelem新开辟空间es并将pval拷贝给es的data域,最后链表长度+1.

11.头插,尾插

直接调用insertprev,头插将plist->head->next传入insertprev即在第一个节点前插入。

尾插将plist->head传入在头节点前插入即在最后一个节点后插入。

12.打印链表

如果存入元素字节小于4,则打印p本身的data值。如果大于4,则打印p指向区域的data值。

13.删除元素

如果元素字节大于4则只设置指针指向。

如果字节大于4就设置指针值指向并释放另外开辟空间。

最后元素个数-1.

14.头删,尾删

尾删即删除头节点前一个元素,将plist->head->prev传入erase即删除最后一个元素。

头删即删除出头节点外第一个元素,将plist->head->next传入erase即删除第一个元素。

15.查找元素

定义指针p遍历链表,如果元素字节大于4,则将p的data与要查找的pval对比相等则返回p。

如果元素字节大于4,则将p指向的data与pval比较相等返回p。

查找失败反回空。

16.获取第一位/最后一位元素

链表非空下如果元素字节小于4,将pdata=plist->head->next->data的值拷贝给pval,即第一个元素。

如果元素字节大于4,将pdata指向区域的data值拷贝给pval.

元素字节小于4,将pdata=plist->head->prev->data的值拷贝给pval,即最后一个元素。

如果元素字节大于4,将pdata指向区域的data值拷贝给pval.

17.删除元素

利用fandval找到后用erase删除。

18.主函数测试

 

#define _CRT_SECURE_NO_WARNINGS
#include"GenLinkList.hpp"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
void printstudent(void* p) {
    student* cp = (student*)p;
    printf("学号:%s,姓名:%s,性别:%s,年龄:%d\n", cp->id, cp->name, cp->sex, cp->age);
}
int main() {
    LinkList ilist;
    InitList(&ilist, sizeof(student));
    student s1 = { "001","zs","man",14 };
    student s2 = { "002","ls","man",15 };
    student s3 = { "003","few","man",35 };
    student s4 = { "004","gr","woman",23 };
    student s5 = { "005","kwe","woman",10 };
    student s6 = { "006","khjq","man",20 };

    Push_back(&ilist, &s1);
    Push_back(&ilist, &s2);
    Push_back(&ilist, &s3);
    Push_front(&ilist, &s4);
    Push_front(&ilist, &s5);
    Push_front(&ilist, &s6);//插入
    printElem(&ilist, printstudent);
    printf("\n----------------------------------- \n");
    pop_back(&ilist);//尾删
    pop_front(&ilist);//头删

    printElem(&ilist, printstudent);//输出

    student stu1;
    GetFront(&ilist, &stu1);
    printstudent(&stu1);//获取第一个
    student stu2;
    GetBack(&ilist, &stu2);
    printstudent(&stu2);//获取最后一个


    student stu;//查询
    memset(&stu, 0, sizeof(student));
    while (scanf("%s %s %s %d", stu.id, stu.name, stu.sex, &stu.age), stu.age != -1) {
        ListNode* p = findval(&ilist, &stu);
        if (NULL == p) {
            printf("find err");
        }
        else {
            printf("%p\n", p);
            printstudent(p->data);
        }
    }


    DestroyList(&ilist);//销毁
    return 0;
}

输入查找值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值