C语言数据结构之单链表操作详解

目录
  • 1、插入操作
  • 2、删除操作
  • 3、查找操作
  • 4、修改操作
  • 5、完整代码

1、插入操作

(1)创建一个新的要插入的结点

(2)将新结点的 next 指针指向插入位置后的结点

(3)将插入位置前的节点指针 next 指向新的结点

注意:步骤(2)(3)的顺序不能颠倒,否则会导致插入位置后的部分链表丢失。

插入位置一共分三种,分别是头部插入、中间插入和尾部插入。

如图:

代码:

link* insertElem(link* p,int elem,int pos){
    link* temp = p;//创建临时结点temp
    //首先找到插入位置的上一个结点
    for(int i=1;i<pos;i++){
        temp=temp->next;
        if(temp==NULL){
            printf("插入位置无效\n");
            return p;
        }
    }
    //创建插入结点c
    link *c=(link*)malloc(sizeof(link));
    c->elem=elem;
    //向链表中插入结点
    c->next = temp->next;
    temp->next=c;
    return p;
}

2、删除操作

(1)将结点从链表中摘下

temp->next=temp->next->next

(2)手动释放掉结点,回收被结点占用的存储空间

如图:

代码:

link*delElem(link*p,int pos){//p是原链表,pos是要删除的元素值
    link* temp=p;
    //遍历到被删除结点的上一个结点
    for(int i =1;i<pos;i++){
        temp=temp->next;
        if(temp->next==NULL){
            printf("没有该结点\n");
            return p;
        }
    }
    link*del=temp->next;//单独开辟一块空间存放被删结点
    temp->next=temp->next->next;//从链表中摘除被删结点
    free(del);//手动释放该结点防止内存泄漏
    return p;
}

3、查找操作

从头遍历链表。

int searchElem(link* p,int elem){
    //新建一个指针t,初始化为头指针 p
    link*t=p;
    int i=1;
    //由于头节点的存在,因此while中的判断为t->next
    while(t->next){
        t=t->next;
        if(t->elem==elem){
            return i;
        }
        i++;
    }
    //程序执行至此处,表示查找失败
    return -1;
}

4、修改操作

先找到目标位置再更改结点的数据域。

link* changeElem(link* p,int pos,int newElem){
    link* temp=p;
    temp=temp->next;//在遍历之前,temp指向首元结点
    //遍历到待更新结点
    for(int i=1;i<pos;i++){
        temp=temp->next;
    }
    temp->elem=newElem;
    return p;
}

5、完整代码

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

typedef struct Link{
    int elem;//数据域
    struct Link *next;//指针域,用来连接后继元素
}link;//link为节点名,每个结点都是一个link结构体 

link* initLink(){
    link *p=(link*)malloc(sizeof(link));//创建头结点
    link*temp = p;//声明一个指针temp指向头结点,也就是头结点的地址赋值给指针变量(注意这不是头指针而是用来连接数组的临时指针变量)
    //生成链表
    for(int i=1;i<5;i++)
    {
        link *a=(link*)malloc(sizeof(link));//生成一个结点
        a->elem=i;//给结点的数据域赋值
        a->next=NULL;//指针域设置为空
        temp->next=a;//上一个结点的指针指向新增结点
        temp=temp->next;//临时指针向后移动也可写成temp=a
    }
    //返回头结点,通过头节点的指针即可找到整个链表
    return p;
} 

link* insertElem(link* p,int elem,int pos){
    link* temp = p;//创建临时结点temp
    //首先找到插入位置的上一个结点
    for(int i=1;i<pos;i++){
        temp=temp->next;
        if(temp==NULL){
            printf("插入位置无效\n");
            return p;
        }
    }
    //创建插入结点c
    link *c=(link*)malloc(sizeof(link));
    c->elem=elem;
    //向链表中插入结点
    c->next = temp->next;
    temp->next=c;
    return p;
}

link* delElem(link*p,int pos){//p是原链表,pos是要删除的元素值
    link* temp=p;
    //遍历到被删除结点的上一个结点
    for(int i =1;i<pos;i++){
        temp=temp->next;
        if(temp->next==NULL){
            printf("没有该结点\n");
            return p;
        }
    }
    link*del=temp->next;//单独开辟一块空间存放被删结点
    temp->next=temp->next->next;//从链表中摘除被删结点
    free(del);//手动释放该结点防止内存泄漏
    return p;
}

link* changeElem(link* p,int pos,int newElem){
    link* temp=p;
    temp=temp->next;//在遍历之前,temp指向首元结点
    //遍历到待更新结点
    for(int i=1;i<pos;i++){
        temp=temp->next;
    }
    temp->elem=newElem;
    return p;
} 

int searchElem(link* p,int elem){
    //新建一个指针t,初始化为头指针 p
    link*t=p;
    int i=1;
    //由于头节点的存在,因此while中的判断为t->next
    while(t->next){
        t=t->next;
        if(t->elem==elem){
            return i;
        }
        i++;
    }
    //程序执行至此处,表示查找失败
    return -1;
} 

void display(link *p){
    link*temp=p;//将temp指向头结点
    printf("链表中的数据为 : ");
    //只要temp指针指向的结点的next不是Null,就执行输出语句。
    while(temp->next){
        temp=temp->next;
        printf("%d ",temp->elem);
    }
    printf("\n");
} 

int main()
{
    //初始化链表
    link *p = initLink();
    display(p);
    printf("在第4的位置插入元素5:\n");
    p = insertElem(p, 5, 4);
    display(p);
    printf("删除元素3:\n");
    p = delElem(p, 3);
    display(p);
    printf("查找元素2的位置为:\n");
    int address = searchElem(p, 2);
    if (address == -1) {
        printf("没有该元素");
    }
    else {
        printf("元素2的位置为:%d\n", address);
    }
    printf("更改第3的位置上的数据为7:\n");
    p = changeElem(p, 3, 7);
    display(p);
    return 0;
}

输出结果:

以上就是C语言数据结构之单链表操作详解的详细内容,更多关于C语言单链表操作的资料请关注我们其它相关文章!

(0)

相关推荐

  • C语言单链表常见操作汇总

    C语言的单链表是常用的数据结构之一,本文总结了单链表的常见操作,实例如下: #include<stdio.h> #include<stdlib.h> //定义单链表结构体 typedef int ElemType; typedef struct Node { ElemType data; struct Node *next; }LNode,*LinkList; //创建单链表 void Build(LinkList L) { int n; LinkList p,q; p=L; pr

  • ​​​​​​​C语言实现单链表基本操作方法

    目录 存储结构 基本功能 头插法创建单链表 尾插法创建单链表 获取指定位置的元素 在指定位置插入元素 删除指定位置的元素 获取单链表的长度 合并两个非递减的单链表 晴链表 遍历打印单链表 附上完整代码 存储结构 typedef int dataType://爱护据类型 typedef struct Node { DataType data; // 结点数据 struct Node *next; // 指向下一个结点的指针 } Node, *LinkList; 基本功能 头插法创建单链表void

  • 用C语言实现单链表的各种操作(二)

    上一篇文章<用C语言实现单链表的各种操作(一)>主要是单链表的一些最基本的操作,下面,主要是一些其他的典型的算法和测试程序. 复制代码 代码如下: /* 对单链表进行排序处理*/struct LNode *sort(struct LNode *head){  LinkList *p;  int n,i,j;  int temp;  n = ListLength(head);  if(head == NULL || head->next == NULL)    return head; 

  • C语言 超详细模拟实现单链表的基本操作建议收藏

    目录 1 链表的概念及结构 2 链表的分类 3 链表的实现无头+单向+非循环链表增删查改实现 3.1 链表的定义 3.2 链表数据的打印 3.3 链表的尾插 3.4 链表空间的动态申请 3.5 链表的头插 3.6 链表的尾删 3.7 链表的头删 3.8 链表任意位置的前插入 3.9 链表任意位置的后插入 3.10 链表的任意位置的删除 3.11 链表的任意位置的前删除 3.12 链表的任意位置的后删除 3.13 链表的销毁 3.14 链表的总结 1 链表的概念及结构 概念:链表是一种物理存储结构

  • C语言中单链表的基本操作指南(增删改查)

    目录 1.链表概述 2.链表的基本使用 2.0 准备工作 2.1 创建节点(结构体) 2.2 全局定义链表头尾指针 方便调用 2.3 创建链表,实现在链表中增加一个数据(尾添加)----增 2.4 遍历链表 -----查 2.5 查询指定的节点 (遍历 一个个找) 2.6 链表清空------全部删除 2.7.在指定位置插入节点 ----在指定位置增 2.8尾删除----删 2.9 删除头------删 2.10 删除指定节点 3. 测试主程序 总结 1.链表概述 链表是一种常见的数据结构.它与

  • 用C语言实现单链表的各种操作(一)

    最近,从新复习了一下数据结构中比较重要的几个部分,现在把自己的成果记录下来,主要就是仿照严蔚敏的<数据结构>(C 语言版),中的例子和后面的习题进行改编的.首先,是单链表的各种实现,其中,包含了一些常考的知识点.例如,单链表的逆置,单链表的合并,找到单链表的中间节点等的算法实现.下面这个是单链表的结构体的定义: 复制代码 代码如下: typedef struct LNode{ ElemType data; struct LNode *next;}LinkList; 下面的基本的单链表的操作:其

  • C语言创建和操作单链表数据结构的实例教程

    1,为什么要用到链表 数组作为存放同类数据的集合,给我们在程序设计时带来很多的方便,增加了灵活性.但数组也同样存在一些弊病.如数组的大小在定义时要事先规定,不能在程序中进行调整,这样一来,在程序设计中针对不同问题有时需要3 0个大小的数组,有时需要5 0个数组的大小,难于统一.我们只能够根据可能的最大需求来定义数组,常常会造成一定存储空间的浪费. 我们希望构造动态的数组,随时可以调整数组的大小,以满足不同问题的需要.链表就是我们需要的动态数组.它是在程序的执行过程中根据需要有数据存储就向系统要求

  • C语言数据结构之单链表操作详解

    目录 1.插入操作 2.删除操作 3.查找操作 4.修改操作 5.完整代码 1.插入操作 (1)创建一个新的要插入的结点 (2)将新结点的 next 指针指向插入位置后的结点 (3)将插入位置前的节点指针 next 指向新的结点 注意:步骤(2)(3)的顺序不能颠倒,否则会导致插入位置后的部分链表丢失. 插入位置一共分三种,分别是头部插入.中间插入和尾部插入. 如图: 代码: link* insertElem(link* p,int elem,int pos){ link* temp = p;/

  • C语言数据结构之单链表存储详解

    目录 1.定义一个链表结点 2.初始化单链表 3.输出链表数据 4.完整代码 如果说,顺序表的所占用的内存空间是连续的,那么链表则是随机分配的不连续的,那么为了使随机分散的内存空间串联在一起形成一种前后相连的关系,指针则起到了关键性作用. 单链表的基本结构: 头指针:永远指向链表第一个节点的位置. 头结点:不存任何数据的空节点,通常作为链表的第一个节点.对于链表来说,头节点不是必须的,它的作用只是为了方便解决某些实际问题. 首元结点:首个带有元素的结点. 其他结点:链表中其他的节点. 1.定义一

  • C语言数据结构之单链表与双链表的增删改查操作实现

    目录 前言 单链表的增删改查 定义结构体以及初始化 增加结点 删除结点 查找修改结点 移除结点 最终效果 双链表的基本操作 初始化建表 遍历双链表 指定位置插入结点 指定位置删除结点 查找结点位置 最终效果 结语 前言 上篇博客分享了创建链表传入二级指针的细节,那么今天就分享几个c语言课程实践设计吧.这些程序设计搞懂了的话相当于链表的基础知识牢牢掌握了,那么再应对复杂的链表类的题也就能慢慢钻研了.学习是一个积累的过程,想要游刃有余就得勤学苦练! 单链表的增删改查 (1)项目需求 构造带有头结点的

  • Go语言数据结构之单链表的实例详解

    目录 任意类型的数据域 实例01 快慢指针 实例02 反转链表 实例03 实例04 交换节点 实例05 任意类型的数据域 之前的链表定义数据域都是整型int,如果需要不同类型的数据就要用到 interface{}. 空接口 interface{} 对于描述起不到任何的作用(因为它不包含任何的method),但interface{}在需要存储任意类型的数值的时候相当有用,因为它可以存储任意类型的数值. 一个函数把interface{}作为参数,那么它可以接受任意类型的值作为参数:如果一个函数返回i

  • C语言数据结构之单链表的实现

    目录 一.为什么使用链表 二.链表的概念 三.链表的实现 3.1 创建链表前须知 3.2 定义结构体 3.3 申请一个节点 3.4 链表的头插 3.5 链表的尾插 3.6 链表的尾删 3.7 链表的头删 3.8 寻找某节点 3.9 在指定节点前插入节点 3.10 删除指定节点前的节点 3.11 链表的销毁 一.为什么使用链表 在学习链表以前,我们存储数据用的方式就是数组.使用数组的好处就是便于查找数据,但缺点也很明显. 使用前需声明数组的长度,一旦声明长度就不能更改 插入和删除操作需要移动大量的

  • C语言数据结构之单链表的查找和建立

    目录 单链表的查找 按位查找 按值查找 单链表的建立 尾插法 头插法建立单链表 单链表的查找 其实在单链表的插入和删除中,我们已经使用过单链表的查找方法,因为插入和删除的前提都是先找到对应的结点,所以这里就不再多解释 按位查找 GetElem(L, i):按位查找操作.获取表 L 中第 i 个位置的元素的值 //按位查找 LNode * GetElem(LinkList L, int i) { if (i < 0) return false; LNode *p; //指针p指向当前扫描到的结点

  • c语言数据结构之栈和队列详解(Stack&Queue)

    目录 简介 栈 一.栈的基本概念 1.栈的定义 2.栈的常见基本操作 二.栈的顺序存储结构 1.栈的顺序存储 2.顺序栈的基本算法 3.共享栈(两栈共享空间) 三.栈的链式存储结构 1.链栈 2.链栈的基本算法 3.性能分析 四.栈的应用——递归 1.递归的定义 2.斐波那契数列 五.栈的应用——四则运算表达式求值 1.后缀表达式计算结果 2.中缀表达式转后缀表达式 队列 一.队列的基本概念 1.队列的定义 2.队列的常见基本操作 二.队列的顺序存储结构 1.顺序队列 2.循环队列 3.循环队列

  • C语言 数据结构与算法之字符串详解

    目录 串的定义 串的比较 串的抽象数据类型 串的初始化 相关定义初始化 定长类初始化 串的堆式顺序存储结构(Heap) 初始化堆字符串 赋值操作 比较两个堆字符串的大小 串的定义 零个或多个字符组成的有限序列 串的比较 串的比较实际上是在比较串中字符的编码 存在某个k < min(n,m),使得ai = bi (i = 1,2,3,4..k) 如果 ak < bk  -->  那么srt1 < srt2 (反之也成立) 除去相等的字符,在第一个不相等的字符位置以Ascii码进行比较

  • Go语言数据结构之选择排序示例详解

    目录 选择排序 动画演示 Go 代码实现 总结 选择排序 选择排序(selection sort)是一种原地(in-place)排序算法,适用于数据量较少的情况.由于选择操作是基于键值的且交换操作只在需要时才执行,所以选择排序长用于数值较大和键值较小的文件. 思想: 对一个数组进行排序,从未排序的部分反复找到最小的元素,并将其放在开头. 给定长度为 nnn 的序列和位置索引i=0 的数组,选择排序将: 遍历一遍序列,寻找序列中的最小值.在 [i...n−1] 范围内找出最小值 minValue

  • 数据结构TypeScript之链表实现详解

    目录 链表结构特点 面向对象方法封装链表 构造函数 基本单元:链表节点 主体:链表 查找节点 增加节点 删除节点 链表结构特点 链表是线性表的其中一种,用于存储有固定顺序的元素.而元素之间会通过”链“连接在一起. 链表存储的元素称为节点.每个节点内部存在两个值.如下: this.element:链表需要存储的单个元素 this.next:指向下一个节点,也就是链表中的”链“,将节点连接在一起. 尝试手动构建链表结构.过程如下: class LinkedListNode { constructor

随机推荐