(三)C语言中阶--单链表

1.单链表结构体特点

typedef struct LNode {   //单链表结构类型
    ElemType data;      //数据域
    struct LNode *next; //指针域(指向下一个结构体的起始地址)
} LNode, *LinkList;

【注】单链表结构体名字不能省略

头指针:
链表中第一个节点的存储位置,用于表示单链表
头结点:
在单链表第一个节点之前附加的一个节点,为了操作上的方便


如果链表有头节点,头指针永远指向头节点,不论链表是否为空,头指针均不为空,头指针时链表的必要元素,标识链表 头节点不是必须的(学习是必须的)


优点缺点
插入和删除操作不需要移动元素,只需要修改指针。单链表附加节点指针域,也存在浪费存储空间的缺点。
不需要大量的连续存储空间。查找操作时需要从头遍历,依次查找,不能随机存取。

插入操作

0. 判断 a."表头插入元素"|b."中间插入元素"|c."表尾插入元素"
1.创建新节点(q), 给新节点申请空间 malloc

a."表头插入元素"(插入位置是a1)
2.让q的指针域next指向ai
3.让原有的头节点指针域指next向q

b."中间插入元素"(插入位置是i-1与i直接)
2.让q的指针域next指向ai
3.让ai-1的指针域next指向q

c."表尾插入元素"(插入位置是an,后面)
2.让an的指针域next指向q
3.给q的next赋值为NULL

头插法新建链表
流程:

开始
定义链表头指针
申请头节点
读取第一个元素
while循环创建链表
打印链表
结束
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;

typedef struct LNode {
    ElemType data;
    struct LNode *next;
} LNode, *LinkList;

void List_head_insert(LinkList &L){
    L=(LinkList) malloc(sizeof (LNode));
    L->next=NULL;
    LNode *s;
    ElemType x;
    scanf("%d", &x);
    while (x!=9999){
        s=(LinkList) malloc(sizeof (LNode));
        s->data=x;
        s->next=L->next;
        L->next=s;
        scanf("%d",&x);
    }
}
void log(LinkList L){
    L=L->next;
    while(L!=NULL){
        printf("%3d", L->data);
        L=L->next;
    }
    printf("\n");
}
int main(){
    LinkList L;
    List_head_insert(L);
    log(L); //打印链表
    return 0;
}

尾插法新建链表
流程:

开始
定义链表头指针
申请头节点
读取第一个元素,while循环创建链表
打印链表
结束
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;

typedef struct LNode {
    ElemType data;
    struct LNode *next;
} LNode, *LinkList;

void List_tail_insert(LinkList &L){
    // 2.1申请头节点
    L=(LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    // 2.2定义尾指针r
    LNode *s, *r=L; //s指向新节点 r指向链表尾
    ElemType x;
    // 3.读取第一个元素
    scanf("%d", &x);
    // 2.2定义位置在r
    while(x!=9999){
        s=(LinkList)malloc(sizeof(LNode));
        s->data=x;
        r->next=s; // 新节点给尾节点的next指针
        r=s; // r指向新的尾部
        scanf("%d",&x);
    }
    r->next=NULL;
}

void log(LinkList L){
    L=L->next;
    while(L!=NULL){
        printf("%3d", L->data);
        L=L->next;
    }
    printf("\n");
}
int main(){
    LinkList L;
    List_tail_insert(L);
    log(L); //打印链表
    return 0;
}

查询操作

  • 按位置查找,查找第i个(头节点不被计算成第一个节点)
    流程:
开始
定义链表指针
尾插法新建链表
查找某个位置的元素值,需要判断该位置是否合法,L是位置0
遍历链表查找值
结束
  • 按值查找
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;

typedef struct LNode {
    ElemType data;
    struct LNode *next;
} LNode, *LinkList;

void List_head_insert(LinkList &L){
    L=(LinkList) malloc(sizeof (LNode));
    L->next=NULL;
    LNode *s;
    ElemType x;
    scanf("%d", &x);
    while (x!=9999){
        s=(LinkList) malloc(sizeof (LNode));
        s->data=x;
        s->next=L->next;
        L->next=s;
        scanf("%d",&x);
    }
}

void List_tail_insert(LinkList &L){
    // 2.1申请头节点
    L=(LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    // 2.2定义尾指针r
    LNode *s, *r=L; //s指向新节点 r指向链表尾
    ElemType x;
    // 3.读取第一个元素
    scanf("%d", &x);
    // 2.2定义位置在r
    while(x!=9999){
        s=(LinkList)malloc(sizeof(LNode));
        s->data=x;
        r->next=s; // 新节点给尾节点的next指针
        r=s; // r指向新的尾部
        scanf("%d",&x);
    }
    r->next=NULL;
}
// 按位置查找
LinkList GetElem(LinkList L, int pointer){
    if (pointer<0){
        return NULL;
    }
    int i=0;
    while (L && i<pointer){
        L=L->next;
        i++;
    }
    return L;
}

// 按值查找
LinkList LocateElem(LinkList L, ElemType val){
    while(L){
        if(L->data==val){ //如果找到返回节点的指针
            return L;
        }
        L=L->next; //如果没有找到向后遍历
    }
    return NULL;
}

void log(LinkList L){
    L=L->next;
    while(L!=NULL){
        printf("%3d", L->data);
        L=L->next;
    }
    printf("\n");
}
int main(){
    LinkList L;
    List_tail_insert(L);
    log(L); //打印链表
    LinkList searchByKey=GetElem(L,3);
    if (searchByKey!=NULL){
        printf("Succeeded in searching by serial number\n");
        printf("%d\n",searchByKey->data);
    }

    LinkList searchByVal = LocateElem(L, 3);
    if(searchByVal!=NULL){
        printf("search by value succeeded\n");
        printf("%d\n",searchByVal->data);
    }
    return 0;
}

在第i个位置插入元素
流程:

开始
定义链表指针
尾插法新建链表
查找某个位置的元素值,需要判断该位置是否合法,L是位置0
通过GetElem获取i-1元素的地址
把新节点插入到i-1元素的后面
结束
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;

typedef struct LNode {
    ElemType data;
    struct LNode *next;
} LNode, *LinkList;
// 尾插法新建链表
void List_tail_insert(LinkList &L){
    // 2.1申请头节点
    L=(LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    // 2.2定义尾指针r
    LNode *s, *r=L; //s指向新节点 r指向链表尾
    ElemType x;
    // 3.读取第一个元素
    scanf("%d", &x);
    // 2.2定义位置在r
    while(x!=9999){
        s=(LinkList)malloc(sizeof(LNode));
        s->data=x;
        r->next=s; // 新节点给尾节点的next指针
        r=s; // r指向新的尾部
        scanf("%d",&x);
    }
    r->next=NULL;
}
// 按位置查找
LinkList GetElem(LinkList L, int pointer){
    if (pointer<0){
        return NULL;
    }
    int i=0;
    while (L && i<pointer){
        L=L->next;
        i++;
    }
    return L;
}
// 打印链表
void log(LinkList L){
    L=L->next;
    while(L!=NULL){
        printf("%3d", L->data);
        L=L->next;
    }
    printf("\n");
}
// 在第i个位置插入
// 往第i个位置插入不会改变L
bool List_front_insert(LinkList L, int pointer, ElemType val){
   LinkList p=GetElem(L, pointer);
    printf("%d\n", p->data);
    if (p==NULL){
        return false;
    }
    LinkList q=(LinkList) malloc(sizeof(LNode));
    q->data=val;
    q->next=p->next;
    p->next=q;
    return true;
}
int main(){
    LinkList L;
    // List_head_insert(L);
    List_tail_insert(L);
    // 在第i个位置插入
    bool ret=List_front_insert(L, 2, 99);
    if (ret){
        printf("insert success\n");
    } else{
        printf("insert failed\n");
    }
    log(L); //打印链表
    return 0;
}
删除操作

流程:

开始
定义链表指针
尾插法新建链表
通过GetElem查找到i-1个位置的元素地址
删除第i个节点,同时释放空间
结束
0.判断 a."表头删除元素"(删除位置是a1)|
    b."中间删除元素"(删除位置i)|
    c."表尾删除元素"(删除位置是an)
1. 查找删除位置i的前驱节点p位置是i-1 q=p.next (q是当前要删除的节点)
2. 把q的指针域next(位置是ai+1)赋值给p的指针域next(位置是ai-1)
3. q断链后free掉
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;

typedef struct LNode {
    ElemType data;
    struct LNode *next;
} LNode, *LinkList;
// 尾插法新建链表
void List_tail_insert(LinkList &L){
    // 2.1申请头节点
    L=(LinkList)malloc(sizeof(LNode));
    L->next=NULL;
    // 2.2定义尾指针r
    LNode *s, *r=L; //s指向新节点 r指向链表尾
    ElemType x;
    // 3.读取第一个元素
    scanf("%d", &x);
    // 2.2定义位置在r
    while(x!=9999){
        s=(LinkList)malloc(sizeof(LNode));
        s->data=x;
        r->next=s; // 新节点给尾节点的next指针
        r=s; // r指向新的尾部
        scanf("%d",&x);
    }
    r->next=NULL;
}
// 按位置查找
LinkList GetElem(LinkList L, int pointer){
    if (pointer<0){
        return NULL;
    }
    int i=0;
    while (L && i<pointer){
        L=L->next;
        i++;
    }
    return L;
}
// 打印链表
void log(LinkList L){
    L=L->next;
    while(L!=NULL){
        printf("%3d", L->data);
        L=L->next;
    }
    printf("\n");
}
// 在第i个位置插入
// 往第i个位置插入不会改变L
bool List_front_insert(LinkList L, int pointer, ElemType val){
   LinkList p=GetElem(L, pointer);
    if (p==NULL){
        return false;
    }
    LinkList q=(LinkList) malloc(sizeof(LNode));
    q->data=val;
    q->next=p->next;
    p->next=q;
    return true;
}
// 单链表删除操作
// 删除操作时不会改变L
bool List_front_delete(LinkList L, int pointer){
	//q是当前要删除的节点
    LinkList q= GetElem(L, pointer);
    //p是当前要删除的节点的前驱
    LinkList p= GetElem(L, pointer-1);
    if(p==NULL){
    	return false;
    }
    //断链
    p->next=q->next;
    free(q);
    return true;
}
int main(){
    LinkList L;
    // List_head_insert(L);
    List_tail_insert(L);
    // 单链表删除
    List_front_delete(L, 2);
    log(L); //打印链表
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Y_努力_strive

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

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

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

打赏作者

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

抵扣说明:

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

余额充值