【C语言基础】顺序表、链表

2023-10-29

一、 线性表

1 线性表定义

请添加图片描述

特点:

  1. 个数有限
  2. 表中数据类型相同
  3. 元素具有逻辑的顺序性,有先后顺序

2 顺序表

用数组实现的

请添加图片描述
请添加图片描述

2.1 插入操作

请添加图片描述

//因为L会改变,所以要引用
bool ListInsert(SqList &L, int i, ElemType element)
{
    //判断不合法情况
    if (i<1 || i>L.length + 1)
    {
        return false;
    }
    //存储空间满了也不能插入
    if (L.length == MaxSize)
    {
        return false;
    }
    //插入元素,插入位置后的元素后移
    for (int j = L.length; j >= i; j--)
    {
        L.data[j] = L.data[j - 1];
    }
    L.data[i - 1] = element;//插入位置的元素
    L.length++;
    return true;
}

2.2 删除操作

请添加图片描述

//删除顺序表  要删除的,有所改变的就加&
//i 是删除元素的位置,del是被删除元素的值
bool ListDelete(SqList& L, int i, ElemType& del) {
    //判断被删除元素的位置是否合法
    if (i < 1 || i>L.length + 1) {
        return false;
    }
    del = L.data[i - 1];
    for (int j = i; j < L.length; j++) {
        L.data[j - 1] = L.data[j];//j赋值为i-1的话,L.data[j] = L.data[j+1],此时需要j<L.length+1,不然多复制了一个
    }
    L.length--;//顺序表长度必须减一
    return true;
}

2.3 查找操作

//查找顺序表
int LocateElem(SqList& L, ElemType element) {
    int i;
    for (i = 0; i < L.length; i++) {
        if (element == L.data[i]) {
            return i + 1;//返回位置,不是下标
        }
      
    }
    return 0;
}

二、单链表

顺序表进行操作移动了大量元素,会造成碎片,因此使用链式结构

一般学习的是具有头结点的链表:
头结点:单链表的第一个结点之前附加了一个结点。头结点的数据域可以不设任何信息,也可以记录表长等信息。头结点的指针域指向线性表的第一个元素结点。

1 头插法创建链表

头插法就是把每个节点插在头结点后面
存储的顺序和输入的顺序是相反的

在这里插入图片描述

请添加图片描述

1.1 代码实现

//1. 头插法
// LNode* 和 LinkList 等价
void list_head_insert(LNode*& L)//这里的LNode* 是结构体指针,&是引用 结构体要改变
{
    L = (LinkList)malloc(sizeof(LNode));//申请头结点空间,头指针指向头结点
    L->next = NULL;
    ElemType x;
    scanf("%d", &x);
    LNode* s;//指向新的节点的指针
    while (x != 9999)
    {
        s = (LinkList)malloc(sizeof(LNode)); // 每次申请一个新的节点
        s->data = x;
        s->next = L->next;//插到头结点后面
        L->next = s;
        scanf("%d", &x);
    }
}

2 尾插法创建链表

尾插法就是把节点插在链表尾部,存储顺序与输入顺序是相同的。

请添加图片描述
把节点连接到链表尾部
在这里插入图片描述

2.1 代码实现

//2. 尾插法
void list_tail_insert(LNode*& L)
{
    L = (LinkList)malloc(sizeof(LNode));//头结点
    L->next = NULL;
    ElemType x;
    scanf("%d", &x);
    //r是一个指针,s也是一个指针变量
    LNode* s, * r = L;//L始终指向头结点,r现在也指向头结点
    while (x != 9999)
    {
        s = (LinkList)malloc(sizeof(LNode));//申请新节点,实际上s指向的就是这块空间的首地址
        s->data = x;
        r->next = s;//r始终指向链表尾部,把新节点连接到尾结点的next
        r = s;//r指向新的尾部![请添加图片描述](https://img-blog.csdnimg.cn/e731289ec1a44a9491652fb13c1b5ba6.png)

        scanf("%d", &x);
    }

3 查找操作

请添加图片描述

3.1 按值查找

从单链表的第一个结点开始,依次比较表中各个结点的数据域的值,若某结点数据域的值等于x,则返回该结点的指针
若整个单链表中没有这样的结点,则返回空

//3. 按值查找
LinkList LocateElem(LinkList L, ElemType SearchVal)
{
    while (L)
    {
        if (L->data == SearchVal)
        {
            return L;
        }
        L = L->next;
    }
    return NULL;
}

3.2 按位查找

从单链表的第一个结点开始,顺着指针域逐个往下搜索,直到找到第 i 个结点为止,否则返回最后一个结点的指针域NULL。

//4.按位置查找
LinkList GetElem(LinkList L, int SearchPos)
{
    int j = 0;
    //判断不合法情况
    if (SearchPos < 0)
    {
        return NULL;
    }
    while (L && j < SearchPos)
    {
        L = L->next;
        j++;
    }
    return L;
}

4 插入操作

首先保证第i个位置的合法性。从表头开始遍历,查找第 i-1个结点,即插入位置的前驱结点为p,然后令新结点q的指针域指向p的后继结点,再令结点p的指针域指向新结点q。

4.1 代码实现

//5. 插入一个元素
bool ListFrontInsert(LinkList L, int i, ElemType InsertVal) //第i个位置
{
    LinkList p = GetElem(L, i - 1); // 利用了按位查找的函数,首先保证该位置的合法性
    if (NULL == p)
    {
        return false;
    }
    LinkList q;
    q = (LinkList)malloc(sizeof(LNode));//为新插入的节点申请空间
    q->data = InsertVal;
    q->next = p->next; //p指针就是插入位置前一个位置
    p->next = q;
    return true;
}

5 删除操作

先检查删除位置的合法性,然后从头开始遍历,找到表中的第 i-1 个结点,即被删除结点的前驱结点p,被删除结点为q,修改p的指针域,将其指向q的下一个结点,最后再释放结点q的存储空间。

5.1 代码实现

//5.删除节点
bool ListDelete(LinkList L, int i)
{
    LinkList p = GetElem(L, i - 1);//查找前驱节点是否存在
    if (NULL == p)
    {
        return false;
    }
    LinkList q = p->next;//指向要删除的节点
    p->next = q->next;//断链
    free(q);//释放,删除操作要释放空间
    return true;
}

6 打印链表

// 6. 打印链表
void print_list(LinkList L)
{
    L = L->next;
    while (L != NULL)
    {
        printf("%3d", L->data);
        L = L->next;
    }
    printf("\n");
}

7 完整代码

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

typedef int ElemType;
typedef struct LNode {
    ElemType data;
    struct LNode* next;
}LNode, * LinkList;//结构体指针
//1. 头插法
// LNode* 和 LinkList 等价
void list_head_insert(LNode*& L)//这里的LNode* 是结构体指针,&是引用 结构体要改变
{
    L = (LinkList)malloc(sizeof(LNode));//申请头结点空间,头指针指向头结点
    L->next = NULL;
    ElemType x;
    scanf("%d", &x);
    LNode* s;//指向新的节点的指针
    while (x != 9999)
    {
        s = (LinkList)malloc(sizeof(LNode)); // 每次申请一个新的节点
        s->data = x;
        s->next = L->next;//插到头结点后面
        L->next = s;
        scanf("%d", &x);
    }
}
//2. 尾插法
void list_tail_insert(LNode*& L)
{
    L = (LinkList)malloc(sizeof(LNode));//头结点
    L->next = NULL;
    ElemType x;
    scanf("%d", &x);
    //r是一个指针,s也是一个指针变量
    LNode* s, * r = L;//L始终指向头结点,r现在也指向头结点
    while (x != 9999)
    {
        s = (LinkList)malloc(sizeof(LNode));//申请新节点,实际上s指向的就是这块空间的首地址
        s->data = x;
        r->next = s;//r始终指向链表尾部,把新节点连接到尾结点的next
        r = s;//s指向新节点
        scanf("%d", &x);
    }
    r->next = NULL;//
}

// 5. 打印链表
void print_list(LinkList L)
{
    L = L->next;
    while (L != NULL)
    {
        printf("%3d", L->data);
        L = L->next;
    }
    printf("\n");
}

//4.按位置查找
LinkList GetElem(LinkList L, int SearchPos)
{
    int j = 0;
    //判断不合法情况
    if (SearchPos < 0)
    {
        return NULL;
    }
    while (L && j < SearchPos)
    {
        L = L->next;
        j++;
    }
    return L;
}
//3. 按值查找
LinkList LocateElem(LinkList L, ElemType SearchVal)
{
    while (L)
    {
        if (L->data == SearchVal)
        {
            return L;
        }
        L = L->next;
    }
    return NULL;
}
//5. 插入一个元素
bool ListFrontInsert(LinkList L, int i, ElemType InsertVal) //第i个位置
{
    LinkList p = GetElem(L, i - 1); // 利用了按位查找的函数,首先保证该位置的合法性
    if (NULL == p)
    {
        return false;
    }
    LinkList q;
    q = (LinkList)malloc(sizeof(LNode));//为新插入的节点申请空间
    q->data = InsertVal;
    q->next = p->next; //p指针就是插入位置前一个位置
    p->next = q;
    return true;
}


int main() {
    LinkList L, search;
//    list_head_insert(L);
    list_tail_insert(L);
    print_list(L);
//    search=GetElem(L,2);
//    if(search!=NULL)
//    {
//        printf("Succeeded in searching by serial number\n");
//        printf("%d\n",search->data);
//    }
//    search=LocateElem(L,6);
//    if(search!=NULL)
//    {
//        printf("Search by value succeeded\n");
//        printf("%d\n",search->data);
//    }
    bool ret;
    ret = ListFrontInsert(L, 4, 99);
    print_list(L);
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C语言基础】顺序表、链表 的相关文章

  • 用Linux搭建web服务器

    搭建web服务器 www 简介 网址及 HTTP 简介 HTTP 协议请求的工作流程 www 服务器的基本配置 实验 实验一 实验二 基于多个虚拟主机IP 基于多个虚拟端口 基于个人Web站点的Web网站 www 简介 网址及 HTTP 简
  • redis缓存击穿、雪崩、穿透及业务场景

    一 缓存击穿 1 概念 缓存击穿 由于并发查询同一热点数据而缓存的热点数据到时失效导致用户请求直接访问数据库 造成数据库压力过大 2 业务场景 一款冷门商品突然爆火 原本redis中冷门商品数据设置了定时过期 爆火后大量请求同时去redis
  • xilinx UART-lite AXI4接口testbench

    升级到vivado2015后 为了升级以及zynq系列FPGA MPSOC考虑 xilinx后续IP将都支持AXI接口 但UART的设计并没有找到example wavform testbench 搞了大半天才把串口调通 串口波特率设置为1
  • 深度学习----tensorflow神经网络(二分类)

    1 自写数据集 二分类 import tensorflow as tf import numpy as np import matplotlib pyplot as plt 使用tensorflow框架 建立神经网络 包含1个隐藏层 使用底
  • Exchange2010批量删除邮件

    在Exchange2010里若要删除某个用户发出的邮件 可以通过EMC控制台授予管理员 管理完全访问权限 通过OWA登录到用户邮箱删除 另外 更简便的方法为使用Exchange2010的命令来处理 可分以下几步处理 1 对操作用户赋予mai
  • Docker的Redis集群部署实战

    参考狂神视频 先把我们的服务器上的容器删除 便于我们下面的测试 root iZwz9hv1phm24s3jicy8x1Z docker rm f docker ps aq 825a4fec0d96 471ad631ae01 65063d37
  • java bufferreader_Java输入流之BufferReader和Scanner的用法!

    原帖地址 http blog csdn net kezhongke article details 7612327 在Java中 我们都知道Java的标准输入串是System in 但是我们却很少在Java中看到谁使用它 这是因为我们平时输

随机推荐

  • [python]csv数据处理 将目录下所有csv文件取出想要的列,去重并存入新csv

    代码 import pandas as pd import os import csv path r home kali Desktop 结果文件10 1 for dirpath dirnames filenames in os walk
  • Python魔术方法-Magic Method

    介绍 在Python中 所有以 双下划线包起来的方法 都统称为 Magic Method 例如类的初始化方法 init Python中所有的魔术方法均在官方文档中有相应描述 但是对于官方的描述比较混乱而且组织比较松散 很难找到有一个例子 构
  • JS版数据结构—树(学习一篇足矣)

    树的深度与广度优先遍历 深度优先遍历 尽可能的搜索树的分支 广度优先遍历 先访问离根节点最近的节点 深度优先遍历 第一步 访问根节点第二部 对根节点的children挨个进行深度优先遍历 const dfs root gt console
  • Android的消息处理机制(图+源码分析)——Looper,Handler,Message

    百度二面的时候 觉得自己源码分析太差 没有深入 面试官估计觉得我很不爽 恩 来吧 自己结合这篇文章 基本上把android消息机制给弄清楚了 http www androidzz com 2011 09 android looper han
  • C++ shared_ptr

    为了解决内存泄漏问题 C 标准库内包含了智能指针 shared ptr是其中的一种 include
  • canal 的 serverMode 模式

    serverMode 为 tcp 需要自定义 canal client 实现消息发送到消息队列 serverMode 为 kafka 或者RocketMQ rabbitmq pulsarmq 不需要 canal client 直接使用消息队
  • java 位运算取8位_【算法】位运算与经典八皇后问题

    文章来源 https mp weixin qq com s 14jQ1yLL4Cw6ufI2E3R yg 作者 码海 前言 位运算在生产或算法解题中并不常见 不过如果你用得好 可以达到事半功倍的效果 而且位运算用得好 也可以极大地提升性能
  • JVM基本结构

    1 JVM 基本架构 2 区域作用 tips Jdk1 6及之前 有永久代 常量池1 6在方法区 Jdk1 7 有永久代 但已经逐步 去永久代 常量池1 7在堆 Jdk1 8及之后 无永久代 常量池1 8在堆 新增元空间 不属于虚拟机 基于
  • Dynamics 365 CRM证书更换

    周末更新公司crm服务器证书时出现一些问题 感谢提供支持的第三方公司 主要步骤参考如下博文https blog csdn net hyhcl article details 109444954 现把存在的问题补充如下 1 如果需要更新crm
  • CTFshow 命令执行 web41

    文章目录 源码 前言 解题 源码
  • 图解 Java 垃圾回收机制,写得非常好! 侵删

    自动垃圾回收是一种在堆内存中找出哪些对象在被使用 还有哪些对象没被使用 并且将后者删掉的机制 所谓使用中的对象 已引用对象 指的是程序中有指针指向的对象 而未使用中的对象 未引用对象 则没有被任何指针给指向 因此占用的内存也可以被回收掉 在
  • 基于STM32F103C8T6ADC检测交流电压

    上篇文章写了硬件部分的实现思路 通过采样电阻的到小电压后经过二级放大电路得到单片机可处理的交流电压 此文介绍了如何采用单片机采集交流电压以及stm32ADC外设的使用 首先是硬件电路部分 电路没有采用核心板 而是直接将芯片焊接到主板上 采用
  • HTML+CSS设计一个简单的水平一级导航栏

    前面我学习了一段时间的HTML和CSS知识 下面我们来运用知识实现一个简单的水平一级导航栏 实现结果 按步骤一步步来 1 首先我们写出它的HTML部分 HTML部分代码 这里是在 div 中使用三个 a 标签 为了方便我没有使用 p 或者
  • Error: That port is already in use.端口号被占用问题解决方法

    标题端口被占用问题 在服务器端先进行查询 然后kill 9 杀死 2473端口 然后在运行Django项目成功
  • MySQL查看数据库相关信息

    https www cnblogs com jiangxiaobo p 6110647 html
  • 百度测开初面面试题分享

    1 java常用的异常处理机制 Java常用的异常处理机制有以下几种 1 try catch finally语句 用于捕获和处理异常 将可能抛出异常的代码放在try块中 然后在catch块中处理异常 无论是否发生异常 finally块中的代
  • Ubuntu/Centos多方法安装mininet

    Ubuntu安装 方法一 apt 安装 sudo apt get install mininet 方法二 源码安装 下载源码 git clone git github com mininet mininet 查看并选择版本 cd minin
  • Vue报错 Property name “xxx“ is not PascalCase

    报错一 Property name my is not PascalCase 首字母需要大写 写成小写的就会报错 报错二 Do not use built in or reserved HTML elements as component
  • 图片下划线 html,HTML 下划线标签元素 HTML下划线标签

    为html字体下划线样式标签 即对文字实现下划线效果 一 认识html下划线标签U 1 html U下划线标签语法 以开始 以结束 u标签不是单独一个标签 而是有开始有闭合的一对标签 使用时候切记勿忘记结束 完成一组u下划线标签使用 内容
  • 【C语言基础】顺序表、链表

    文章目录 一 线性表 1 线性表定义 2 顺序表 2 1 插入操作 2 2 删除操作 2 3 查找操作 二 单链表 1 头插法创建链表 1 1 代码实现 2 尾插法创建链表 2 1 代码实现 3 查找操作 3 1 按值查找 3 2 按位查找