链表(7.27)

3.3 链表的实现
3.3.1头插
原理图:
newnode为新创建的节点
实现:
//头插
//让新节点指向原来的头指针(节点),即新节点位于开头
newnode->next = plist;
//再让头指针(节点)指向新节点,新节点就成为了头节点
plist = newnode;

此操作在链表为空的情况下也能正常运行。

3.3.2尾插
原理:创建一个新节点,先通过局部变量 tail 遍历找到指向的下一个节点为空的节点(即倒数第二个节点),然后将该节点与新节点链接起来。
初步实现:
// 单链表尾插
//第一个参数为头指针的拷贝(形参)
void SListPushBack(SLTNode* phead, SLTDataType x)
{SLTNode* tail = phead;//创建要插入的新节点SLTNode* newnode = BuySListNode(x);//遍历下一个节点指向为空的节点while (tail->next != NULL){tail = tail->next;}//将该节点与新节点链接起来tail->next = newnode;
}

phead,tail,newnode为局部变量,出了作用域就会自动销毁,而链表的节点存在于堆上,不会自动销毁。

上面的步骤是在原有链表的前提下进行的,如果链表为空呢?

需要让新节点充当头节点,也就是要让 plist(结构体指针)(头指针) 指向新节点,因此我们尝试将新创建的节点赋给头指针

if (phead == NULL){phead = newnode;}

但这个做法对吗,显然不对,形参是实参的一份临时拷贝,改变形参不影响实参,出了这个作用域,这两个指针就销毁了,plist也没有改变。

plist 是结构体类型的指针,要改变它的值,在函数中就需要传它的地址,也就是指针的地址。

//第一个参数为头指针的拷贝(形参)
void SListPushBack(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySListNode(x);//如果链表为空//*pphead==plistif (*pphead == NULL){*pphead = newnode;}else{SLTNode* tail = *pphead;//创建要插入的新节点//遍历下一个节点指向为空的节点while (tail->next != NULL){tail = tail->next;}//将该节点与新节点链接起来tail->next = newnode;}
}

 总结:

改变结构体用结构体指针;

改变结构体指针用结构体二级指针;

3.3.3头插

本篇开头已经在函数外实现过了,现在在函数中实现一次。

每一次头插都要改变 plist 头指针,因此也需要传二重指针

// 单链表的头插
void SListPushFront(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySListNode(x);newnode->next = *pphead;*pphead = newnode;
}

3.3.4尾删

根据剩余节点的不同,分3种情况

1.链表为空

这是一种异常的情况,我们需要使用断言对参数加以限制,以防传空指针情况的出现。

assert(*pphead);

2.链表只剩一个节点

再删掉就为空,这时候就需要释放节点的空间,并将头指针置空,就涉及到了头指针的改变,需要引用二级指针。

    if ((*pphead)->next == NULL)
    {
        free(*pphead);
        *pphead = NULL;
    }

3.链表中包含>1个节点

用 tail 找到末尾节点并将其删除,将倒数第二个节点置空,该情况下不需要二级指针。

原理图:

SLTNode* tailPre = NULL;
        SLTNode* tail = *pphead;
        while (tail->next != NULL)
        {
            tailPre = tail;
            tail = tail->next;
        }
        free(tail);
        tailPre->next = NULL;

3.3.5头删

让头指针指向第二个节点,将第一个节点释放。

// 单链表头删
void SListPopFront(SLTNode** pphead)
{assert(*pphead);//第二个节点SLTNode* newhead = (*pphead)->next;//释放第一个节点free(*pphead);//让第二个节点成为新的头节点*pphead = newhead;
}

完整代码:

头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;
//打印链表
void SLTPrint(SLTNode* pahead);
//开辟一个节点并赋值
SLTNode* BuySLTNode(SLTDataType X);
// 单链表尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);
// 单链表的头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);
// 单链表的尾删
void SLTPopBack(SLTNode** pphead);
// 单链表头删
void SLTPopFront(SLTNode** pphead);

 测试文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
void TestSList1()
{int n = 0;printf("请输入链表的长度\n");scanf("%d", &n);printf("请依次输入每个节点的值\n");//创建头指针SLTNode* plist = NULL;for (int i = 0; i < n; i++){int val = 0;scanf("%d", &val);//开辟新节点SLTNode* newnode = BuySLTNode(val);//头插//让新节点指向原来的头指针(节点),即新节点位于开头newnode->next = plist;//再让头指针(节点)指向新节点,新节点就成为了头节点plist = newnode;}SLTPushBack(&plist, 100);SLTPrint(plist);
}
void TestSList2()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPushBack(&plist, 5);SLTPrint(plist);SLTPushFront(&plist, 10);SLTPushFront(&plist, 20);SLTPushFront(&plist, 30);SLTPushFront(&plist, 40);SLTPrint(plist);
}
void TestSList3()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPushBack(&plist, 5);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);SLTPopBack(&plist);SLTPrint(plist);// SLTPopBack(&plist);// SLTPrint(plist);
}
void TestSList4()
{SLTNode* plist = NULL;SLTPushBack(&plist, 1);SLTPushBack(&plist, 2);SLTPushBack(&plist, 3);SLTPushBack(&plist, 4);SLTPushBack(&plist, 5);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);SLTPrint(plist);SLTPopFront(&plist);//SLTPopFront(&plist);SLTPrint(plist);
}
//void TestSList5()
//{
//	SLTNode* plist = NULL;
//	SLTPushBack(&plist, 1);
//	SLTPushBack(&plist, 2);
//	SLTPushBack(&plist, 3);
//	SLTPushBack(&plist, 4);
//	SLTPushBack(&plist, 5);
//	SLTPrint(plist);
//
//	SLTNode* pos = SLTFind(plist, 3);
//	SLTInsert(&plist, pos, 30);
//}
int main()
{//TestSList1();TestSList2();/*TestSList3();TestSList4();TestSList5();*/return 0;
}

实现文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"
void SLTPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}//结束,打印空printf("NULL\n");
}
//开辟节点并赋值
SLTNode* BuySLTNode(SLTDataType X)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc");exit(-1);}newnode->data = X;newnode->next = NULL;return newnode;
}
// 单链表尾插
//第一个参数为头指针的拷贝(形参)
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySLTNode(x);//如果链表为空//*pphead==plistif (*pphead == NULL){//改变结构体指针,用结构体二级指针*pphead = newnode;}else{SLTNode* tail = *pphead;//创建要插入的新节点//遍历下一个节点指向为空的节点while (tail->next != NULL){tail = tail->next;}//改变结构体用结构体指针,将该节点与新节点链接起来tail->next = newnode;}
}
// 单链表的头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuySLTNode(x);newnode->next = *pphead;*pphead = newnode;
}
// 单链表的尾删
void SLTPopBack(SLTNode** pphead)
{//限制参数不为空assert(*pphead);//仅有一个节点的情况if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}//有两个及以上节点的情况else{//尾节点的前一个节点SLTNode* tailPre = NULL;SLTNode* tail = *pphead;while (tail->next != NULL){tailPre = tail;//tail往后走之前赋给前一个指针tail = tail->next;}free(tail);tailPre->next = NULL;}
}
// 单链表头删
void SLTPopFront(SLTNode** pphead)
{assert(*pphead);//第二个节点SLTNode* newhead = (*pphead)->next;//释放第一个节点free(*pphead);//让第二个节点成为新的头节点*pphead = newhead;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/153492.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【亲测】简易商城小程序源码-易优CMS后台

易优小程序是基于前端开源小程序后端易优CMS标签化API接口&#xff0c; 是一套开源、快速搭建个性化需求的小程序CMS。轻量级TP底层框架&#xff0c;前后端分离&#xff0c; 标签化API接口可对接所有小程序&#xff0c;支持二次开发。即使小白用户也能轻松搭建制作一套完整的线…

实现一个简单的线性回归和多项式回归(2)

对于多项式回归&#xff0c;可以同样使用前面线性回归中定义的LinearRegression算子、训练函数train、均方误差函数mean_squared_error&#xff0c;生成数据集create_toy_data,这里就不多做赘述咯~ 拟合的函数为 def sin(x):y torch.sin(2 * math.pi * x)return y1.数据集的建…

go的面向对象学习

文章目录 面向对象编程(上)1.问题与解决思路2.结构体1》Golang语言面向对象编程说明2》结构体与结构体变量(实例/对象)的关系的示意图3》入门案例(using struct to solve the problem of cat growing) 3.结构体的具体应用4.创建结构体变量和访问结构体字段5.struct类型的内存分…

axios的get请求时数组参数没有下标

开发新项目过程中 发现get请求时 数组参数没有下标 这样肯定是不行的 后端接口需要数组[0]: 7 数组[1]:4这样的数据 原因是因为在请求拦截器没有处理需要的参数 解决方法 在请求拦截器 处理一下参数 import axios, { AxiosError, AxiosInstance, AxiosRequestHeaders } fro…

解决yolo无法指定显卡的问题,实测v5、v7、v8有效

方法1 基本上这个就能解决了&#xff01;&#xff01;&#xff01; 在train.py的最上方加上下面这两行&#xff0c;注意是最上面&#xff0c;其次指定的就是你要使用的显卡 import os os.environ[CUDA_VISIBLE_DEVICES]6方法2&#xff1a; **问题&#xff1a;**命令行参数指…

HTML5+CSSday4综合案例二——banner效果

bannerCSS展示图&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"wi…

Redis安装教程

官网地址 地址链接&#xff1a;传送门 安装步骤 这里有更多版本的选择 进去根据自己的需要选择版本&#xff0c;我这里用的7系列的稳定版。

AI视频监控平台EasyCVR接入海康SDK出现异常,该如何解决?

安防监控系统/视频集中存储/云存储/视频监控管理平台EasyCVR能在复杂的网络环境中&#xff0c;将分散的各类视频资源进行统一汇聚、整合、集中管理&#xff0c;实现视频资源的鉴权管理、按需调阅、全网分发、智能分析等。 有用户反馈&#xff0c;在使用视频监控系统EasyCVR接入…

汽车烟雾测漏仪(EP120)

【汽车烟雾测漏仪&#xff08;EP120&#xff09;】 此烟雾测漏仪专为车辆管道&#xff08;油道、气道、冷却管道&#xff09; 的泄露检测而设计。适用于所有轻型 汽车、摩托车、轻卡、游艇等。 【特点】 具有空气模式和烟雾模式。空气模式&#xff0c;无需烟雾&#xff0c;检测…

打造虚拟企业展厅,开启商务活动新时代

引言: 虚拟企业展厅是一种基于数字技术的全新商务模式&#xff0c;正在改变传统商务活动的方式&#xff0c;它比传统的企业展厅更便利&#xff0c;也更能凸显企业优势&#xff0c;展示企业风貌。 一&#xff0e;虚拟企业展厅的好处 1.打破地域限制 传统的商务活动通常需要参…

12. Java异常及异常处理处理

Java —— 异常及处理 1. 异常2. 异常体系3. 常见Exception4. 异常处理4.1 try finally catch关键字4.2 throws和throw 自定义异常4.3 finally&#xff0c;final&#xff0c;finalize三者的区别 1. 异常 异常&#xff1a;在程序执行过程中发生的意外状况&#xff0c;可能导致程…

JVM命令行监控工具

JVM命令行监控工具 概述 性能诊断是软件工程师在日常工作中需要经常面对和解决的问题&#xff0c;在用户体验至上的今天&#xff0c;解决好应用的性能问题能带来非常大的收益。 Java作为最流行的编程语言之一&#xff0c;其应用性能诊断一直受到业界广泛关注&#xff0c;可能…

vue3 集成 tailwindcss

tailwindcss 介绍 Tailwind CSS 是一个流行的前端框架&#xff0c;用于构建现代、响应式的网页和 Web 应用程序。它的设计理念是提供一组可复用的简单、低级别的 CSS 类&#xff0c;这些类可以直接应用到 HTML 元素上&#xff0c;从而加速开发过程并提高样式一致性。 主要特点…

超市微信小程序是怎么做的

市微信小程序是利用微信小程序平台为超市或零售商提供线上销售服务的一种应用。通过小程序&#xff0c;超市可以向消费者提供更加便捷、快速、个性化的购物体验&#xff0c;从而提升销售业绩、增加客户满意度。以下是超市微信小程序可以实现的一些主要功能。 一、商品展示与搜索…

linux centos出现No space left on device解决方案

问题是因为系统磁盘空间不足 解决方法: 找到那个磁盘不足问题 df -lh 发现/dev/mapper/cl-root磁盘已用50G,有如下 解决方案&#xff1a; 1、如果是虚拟机可以通过分配空间使其空间增加 2、将其他不常用磁盘空间分配给cl-root如&#xff08; /dev/mapper/cl-home &#…

XSS原理

原理&#xff1a; 这是一种将任意 Javascript 代码插入到其他Web用户页面里执行以达到攻击目的的漏洞。攻击者利用浏览器的动态展示数据功能&#xff0c;在HTML页面里嵌入恶意代码。当用户浏览改页时&#xff0c;这些潜入在HTML中的恶意代码会被执行&#xff0c;用户浏览器被攻…

6-3 递增的整数序列链表的插入 分数 5

List Insert(List L, ElementType X) {//创建结点List node (List)malloc(sizeof(List));node->Data X;node->Next NULL;List head L->Next; //定位real头指针//空链表 直接插入if (head NULL) {L->Next node;node->Next head;return L;}//插入数据比第…

哈夫曼树哈夫曼编码知识点

目录 前言 哈夫曼树 1.相关背景 2.基本概念 3.什么是哈夫曼树 3.特点 4.哈夫曼树的构造&#xff08;哈夫曼算法&#xff09; 5.带权路径长度计算 哈夫曼编码&#xff08;哈夫曼树的应用&#xff09; 1.基本概念 2.编码方式 3.编码依据 4.小试牛刀&#xff08;习题&am…

智慧楼宇3D数据可视化大屏交互展示实现了楼宇能源的高效、智能、精细化管控

智慧园区是指将物联网、大数据、人工智能等技术应用于传统建筑和基础设施&#xff0c;以实现对园区的全面监控、管理和服务的一种建筑形态。通过将园区内设备、设施和系统联网&#xff0c;实现数据的传输、共享和响应&#xff0c;提高园区的管理效率和运营效益&#xff0c;为居…

socket can查看详细信息 命令 ip -details -statistics link show can0

ip -details -statistics link show can0 ip -details link show can0 ip -statistics link show can0 也可以像第一行那样结合使用