数据结构之---线性表其二---单向链表

线性表的链式存储结构---用链式存储结构实现的线性表就叫(单向)链表

链表:结点和结点相连

结点:包含数据域和指针域

头指针:保存第一个结点地址的指针,头指针通过标记第一个结点,从而标记了整个链表,因此用头指针来命名整个链表。

链表分为带头结点的链表和不带头结点的链表

头结点:带头结点的链表的第一个结点(头结点数据域有数据但不是程序员放的,是随机的,只要分配了空间就是有数据的)

首元结点:保存线性表中第一个数据的结点

第一个节点:头指针指向的结点

链表包含:头指针和结点(或头结点)

链表操作:增删改查

单链表操作:

结构体作为结点

复制代码
//定义一个结构体结点
typedef struct Node
{
    int data;//存储数据
    struct Node *next;//下一个结点地址
}Node,*LinkList;

(1)初始化

复制代码
//初始化单链表,定义一个头结点
LinkList InitLinkList(){
    Node *node = (Node*)malloc(sizeof(Node));
    if(node!=NULL)
    {
    node->next = NULL;
    return node;
    }else{
        printf("内存申请失败\n");
        return node;
    }
    /*
    这样行吗?
    Node d;
    d.next = NULL;
    return &d;
    答案是不行的,
    因为d是一个变量,存放在栈区,当函数调用完毕之后该变量内存会被系统回收,此时&d = NULL;
    */
}

(2)添加数据

头插法:

复制代码
//头插法(在头结点后一个位置添加数据k)
LinkList headInsert(LinkList l,int k){
    //1.新结点s
    Node *s = (Node*)malloc(sizeof(Node));
    //2.加入数据
    if(s!=NULL)
    {
    s->data = k;
    //3.指针域指向首元结点,因为是在头结点和首元结点之间插入数据
    s->next = l->next;//
    //4.头结点指向s;
    l->next = s;

    return l;
    }else{
        printf("内存申请失败\n");
        return s;
    }
}

尾插法:

复制代码
//尾插法
LinkList rearInsert(LinkList l,int k){
    Node *s = (Node*)malloc(sizeof(Node));
    if(s!=NULL)
    {
    s->data = k;
    s->next = NULL;
    Node *n = l;
    while(n->next!=NULL)
    {
        n = n->next;
    }
    n->next = s;
    return l;
    }else{
        printf("内存申请失败\n");
        return s;
    }
}

中间插入(在数据x后面插入数据k):

复制代码
//指定位置插入在x后面插入k
LinkList middleInsert(LinkList l,int x,int k){
    Node *s = (Node*)malloc(sizeof(Node));
    if(s == NULL)
    {
        printf("内存申请失败\n");
        return l;
    }
    s->data = k;
    Node *n = Find(l,x);
    if(n!=NULL)
    {
        s->next = n->next;
        n->next = s;
        return l;
    }else{
        printf("查无此数据\n");
        return l;
    }

}

(3)查找

复制代码
//查找
Node *Find(LinkList l,int k){
    Node *p = l->next;//从首元结点开始找
    while(p!=NULL)
    {
        if(p->data == k)
        {
            return p;
        }else{
            p = p->next;
        }
    }
    return p;
}

(4)删除

改正:第三行是从首元结点开始

复制代码
//删除结点x
LinkList delete(LinkList l,int x){
    Node *s = l->next;//从头结点开始
    Node *preS = l;//指向前一个结点
    while(s!=NULL&&s->data!=x)
    {
        preS = s;
        s = s->next;
    }
    if(s == NULL)
    {
        printf("%d不存在\n",x);
        return l;
    }
    preS->next = s->next;
    free(s);//释放空间,但地址值依然保存
    s = NULL;//防止野指针情况出现
    return l;

}

(5)输出

复制代码
//输出
void printff(LinkList l){
    Node *s = l->next;
    if(s == NULL)
    {
        printf("空指针\n");
    }
    while(s!=NULL)
    {
        printf("%d ",s->data);
    }
}

(6)修改

复制代码
//修改结点数据y为k
LinkList changeNode(LinkList l ,int y,int k){
    Node *n = Find(l,y);
    if(n == NULL)
    {
        printf("查无此数据\n");
        return l;
    }
    n->data = k;
    return l;

链表优缺点:

优点:灵活,便捷,因为要修改链表中的某一个数据时,不用移动其他的数据

缺点: 不支持随机存取,只能从头指针开始查找。

相关推荐
梵刹古音2 分钟前
【C语言】 指针与数据结构操作
c语言·数据结构·算法
爱敲代码的TOM1 小时前
数据结构总结
数据结构
皮皮哎哟3 小时前
数据结构:嵌入式常用排序与查找算法精讲
数据结构·算法·排序算法·二分查找·快速排序
堕2744 小时前
java数据结构当中的《排序》(一 )
java·数据结构·排序算法
2302_813806224 小时前
【嵌入式修炼:数据结构篇】——数据结构总结
数据结构
Wei&Yan5 小时前
数据结构——顺序表(静/动态代码实现)
数据结构·c++·算法·visual studio code
long3165 小时前
Aho-Corasick 模式搜索算法
java·数据结构·spring boot·后端·算法·排序算法
张张努力变强8 小时前
C++ STL string 类:常用接口 + auto + 范围 for全攻略,字符串操作效率拉满
开发语言·数据结构·c++·算法·stl
wWYy.8 小时前
数组快排 链表归并
数据结构·链表
李斯啦果8 小时前
【PTA】L1-019 谁先倒
数据结构·算法