当前位置: 首页 > article >正文

顺序表——C语言实现

目录

一、线性表

二、顺序表

1.实现动态顺序表

SeqList.h

SeqList.c

Test.c

问题

经验:free 出问题,2种可能性

解决问题

(2)尾删

(3)头插,头删

(4)在 pos 位插

(5)在 pos 位删

(6)查找

2.整体代码

SeqList.h

SeqList.c

test.c


一、线性表

线性表(linear list)是 n 个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串。

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组链式结构的形式存储。

二、顺序表

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

分类:
(1)静态顺序表:使用定长数组存储元素
(2)动态顺序表:使用动态开辟的数组存储

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小

1.实现动态顺序表

SeqList.h
typedef int SLDataType;
#define INIT_CAPACITY 4 // 初始化容量typedef struct SeqList
{SLDataType* a;int size;     // 有效数据个数int capacity; // 空间容量
}SL;// 增删查改
void SLInit(SL* ps);
void SLDestroy(SL* ps);//打印顺序表数据
void SLPrint(SL* ps);void SLPushBack(SL* ps, SLDataType x); // 尾插
void SLPopBack(SL* ps); // 尾删
void SLPushFront(SL* ps, SLDataType x); // 头插
void SLPopFront(SL* ps); // 头删// 扩容,2倍合适
void SLCheckCapacity(SL* ps);
SeqList.c
void SLInit(SL* ps)
{assert(ps);ps->a = (SLDataType*)malloc(sizeof(SLDataType) * INIT_CAPACITY);if (ps->a == NULL){perror("malloc fail");return;}ps->size = 0;ps->capacity = INIT_CAPACITY;
}void SLDestroy(SL* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0; // 结合性,从右往左赋值
}void SLPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; ++i){printf("%d ", ps->a[i]);}printf("\n");
}// 扩容,2倍合适
void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2);//思考这里对不对if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp; // 防止不是原地扩容ps->capacity *= 2;}}void SLPushBack(SL* ps, SLDataType x) // 尾插
{assert(ps);// 扩容  2倍合适SLCheckCapacity(ps);ps->a[ps->size++] = x;
}
Test.c
void TestSeqList1()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPrint(&s);SLDestroy(&s);
}int main()
{TestSeqList1();return 0;
}

运行上面的代码,顺序表里插入1234:,程序没毛病


问题

void TestSeqList1()
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPushBack(&s, 5);SLPrint(&s);SLDestroy(&s);
}

奇怪的事情发生了:

SLPushBack(&s, 6);
SLPushBack(&s, 7);

奇怪的事情又发生了:    光标在闪

这里反反复复调试都发现不了问题


经验:free 出问题,2种可能性

(1)野指针 或 位置不对。这种情况不多
eg:申请一块空间,从中间位置释放,报错。(应该从起始位置释放)
(2)指针指向的空间(数组)上面,可能有越界。

  • 下标越界
  • 开少了

解决问题

realloc 返回的是地址,->a,a 我们没有动过,动的都是 a 指向的内容
free 有时候出问题,通常不是free ( ) 里面有问题,而是前面有越界

仔细查,动空间的只有 SLPushBack(    )

// 扩容,2倍合适
void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2);//思考这里对不对if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp; // 防止原地扩容ps->capacity *= 2;}}void SLPushBack(SL* ps, SLDataType x) // 尾插
{assert(ps);// 扩容  2倍合适SLCheckCapacity(ps);ps->a[ps->size++] = x;
}

ps->a[ps->size++] = x; 逻辑没有问题,问题大概率出现在扩容

先看下标越界了吗?size 没有越界的可能性

还有一种可能是开少了。
你以为你原来是 4 个,扩容到 8 个。你以为你有 8 个,实际上没有 8 个。你当成 8 个访问的呀,就越了。

8 个 SLDataType 是 4*8=32 字节。
ps->capacity * 2 这里是 4*2=8 字节


正确写法:

// 扩容  2倍合适
void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * ps->capacity * 2);if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity *= 2;}
}void SLPushBack(SL* ps, SLDataType x) // 尾插
{assert(ps);SLCheckCapacity(ps);ps->a[ps->size++] = x;
}

 问题解决

(2)尾删

void SLPopBack(SL* ps) // 尾删
{assert(ps);//ps->a[ps->size - 1] = 0; 加上没用ps->size--;
}

由 size 遍例顺序表,size -- 后,前 size-1个是有效数据,第 size 个访问不到了

注意:这里不用释放,一部分一部分释放会报错。
但是不用担心,当我们不用这个顺序表时会 SLDestroy(&s) ; 空间还是会释放的


删空了还删,会报错。所以要检查

void SLPopBack(SL* ps) // 尾删
{assert(ps);// 温柔的检查if (ps->size == 0)return;ps->size--;
}

断言 assert 会直接告诉你哪出错了,并且终止掉程序

void SLPopBack(SL* ps) // 尾删
{assert(ps);// 暴力检查assert(ps->size > 0);ps->size--;
}

(3)头插,头删

要挪动数据,以实现顺序表连续性
顺序表尾插,尾删效率不错。头插,头删效率不太行。但有时候就要头插,头删

void SLPushFront(SL* ps, SLDataType x) // 头插
{assert(ps);SLCheckCapacity(ps);//挪动memmove(&(ps->a[1]), &(ps->a[0]), sizeof(SLDataType) * ps->size);//头插ps->a[0] = x;ps->size++;
}void SLPopFront(SL* ps) // 头删
{assert(ps);assert(ps->size > 0);memmove(&(ps->a[0]), &(ps->a[1]), sizeof(SLDataType) * ps->size);ps->size--;
}

我们发现:插入N个数据。尾插时间复杂度:O(N)     头插时间复杂度:O(N^2)
头插1万个数据,要执行1亿次。所以,尽量避免使用头插

疑问:为什么头插用memmove库函数了,时间复杂度还是O(N^2)
答:虽然我们用的是库函数,一步到位,没有用模拟实现。我们分析它的时间复杂度,还是要看到本质,本质就是模拟实现,通过模拟实现分析它的时间复杂度。

本质:

void SLPushFront(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;
}

可以看到,头插1个数据,执行N次,时间复杂度O(N)。头插N个数据,执行N^2次,时间复杂度O(N^2)  从模拟实现的角度看,它是一个等差数列

(4)在 pos 位插

// 顺序表在pos位置插入x
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);// 插入时 = size 相当于尾插SLCheckCapacity(ps);//挪动memmove(&(ps->a[pos + 1]), &(ps->a[pos]), sizeof(SLDataType) * (ps->size - pos));//插入ps->a[pos] = x;ps->size++;
}

我们可以简化头插(在第0位),尾插(在第size位)。

void SLPushBack(SL* ps, SLDataType x) // 尾插
{assert(ps);/*SLCheckCapacity(ps);ps->a[ps->size++] = x;*/SLInsert(ps, ps->size, x);
}void SLPushFront(SL* ps, SLDataType x) // 头插
{assert(ps);/*SLCheckCapacity(ps);//挪动memmove(&(ps->a[1]), &(ps->a[0]), sizeof(SLDataType) * ps->size);//头插ps->a[0] = x;ps->size++;*/SLInsert(ps, 0, x);
}

(5)在 pos 位删

// 顺序表删除pos位置的值
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//覆盖memmove(&(ps->a[pos]), &(ps->a[pos + 1]), sizeof(SLDataType) * (ps->size - pos - 1));ps->size--;
}

可以简化 头删,尾删 的代码。

void SLPopBack(SL* ps) // 尾删
{assert(ps);/*// 暴力检查assert(ps->size > 0);温柔的检查//if (ps->size == 0)//	return;ps->size--;*/SLErase(ps, ps->size - 1);
}void SLPopFront(SL* ps) // 头删
{assert(ps);/*assert(ps->size > 0);memmove(&(ps->a[0]), &(ps->a[1]), sizeof(SLDataType) * ps->size);ps->size--;*/SLErase(ps, 0);
}

疑问:用这个新的代码尾删,假设现在size = 8,根据上面代码,最大容量 capacity 也 = 8。要尾删,删下标为7的位置,传给 pos,pos+1 = 8 。SLErase 里面 &(ps->a[pos + 1]) 不会越界访问吗?
解答:这时要 memmove 移动 ps->size - pos - 1 = 0 个字节。我们看 memmove 模拟实现:num 是要移动的字节个数,这里 num = 0 ,循环没进去,也就不存在越界访问了

(6)查找

//顺序表查找
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (x == ps->a[i]){return i;}}return -1;
}

问:为什么删除后,不用 realloc 回收一部分内存的使用权?
答:当扩容时,realloc 开内存,分为异地扩容,本地扩容。想要新开辟空间,如果原空间后面的大小够,就本地扩容,效率高。后面大小不够,就异地扩容,效率低
而现代计算机内存空间的数量很多,不怕浪费,为保证运行效率,宁愿占着茅坑不拉屎。

当我们确认不再使用时,也会 SLDestroy 释放全部空间

问:为什么不写菜单?
答:数据结构部分,菜单没有什么价值。而且不好调试。菜单一般在命令行程序,控制数据库的服务器,会输入选项(指令去控制)。
写菜单的话,也不要一上来就写菜单。先在 test.c 里写一组一组测试 ,测的没问题了,再写菜单

2.整体代码

SeqList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SLDataType;
#define INIT_CAPACITY 4 // 初始化容量typedef struct SeqList
{SLDataType* a;int size;     // 有效数据个数int capacity; // 空间容量
}SL;// 增删查改
void SLInit(SL* ps);
void SLDestroy(SL* ps);//打印顺序表数据
void SLPrint(SL* ps);void SLPushBack(SL* ps, SLDataType x); // 尾插
void SLPopBack(SL* ps); // 尾删
void SLPushFront(SL* ps, SLDataType x); // 头插
void SLPopFront(SL* ps); // 头删// 顺序表查找
int SLFind(SL* ps, SLDataType x);
// 顺序表在pos位置插入x
void SLInsert(SL* ps, int pos, SLDataType x);
// 顺序表删除pos位置的值
void SLErase(SL* ps, int pos);// 扩容,2倍合适
void SLCheckCapacity(SL* ps);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLInit(SL* ps)
{assert(ps);ps->a = (SLDataType*)malloc(sizeof(SLDataType) * INIT_CAPACITY);if (ps->a == NULL){perror("malloc fail");return;}ps->size = 0;ps->capacity = INIT_CAPACITY;
}void SLDestroy(SL* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->capacity = ps->size = 0; // 结合性,从右往左赋值
}void SLPrint(SL* ps)
{assert(ps);for (int i = 0; i < ps->size; ++i){printf("%d ", ps->a[i]);}printf("\n");
}// 扩容  2倍合适
void SLCheckCapacity(SL* ps)
{assert(ps);if (ps->size == ps->capacity){SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * ps->capacity * 2);if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity *= 2;}
}void SLPushBack(SL* ps, SLDataType x) // 尾插
{assert(ps);/*SLCheckCapacity(ps);ps->a[ps->size++] = x;*/SLInsert(ps, ps->size, x);
}void SLPopBack(SL* ps) // 尾删
{assert(ps);/*// 暴力检查assert(ps->size > 0);温柔的检查//if (ps->size == 0)//	return;ps->size--;*/SLErase(ps, ps->size - 1);
}void SLPushFront(SL* ps, SLDataType x) // 头插
{assert(ps);/*SLCheckCapacity(ps);//挪动memmove(&(ps->a[1]), &(ps->a[0]), sizeof(SLDataType) * ps->size);//头插ps->a[0] = x;ps->size++;*/SLInsert(ps, 0, x);
}void SLPopFront(SL* ps) // 头删
{assert(ps);/*assert(ps->size > 0);memmove(&(ps->a[0]), &(ps->a[1]), sizeof(SLDataType) * ps->size);ps->size--;*/SLErase(ps, 0);
}//顺序表查找
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){if (x == ps->a[i]){return i;}}return -1;
}// 顺序表在pos位置插入x
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);// 插入时 = size 相当于尾插SLCheckCapacity(ps);//挪动memmove(&(ps->a[pos + 1]), &(ps->a[pos]), sizeof(SLDataType) * (ps->size - pos));//插入ps->a[pos] = x;ps->size++;
}// 顺序表删除pos位置的值
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);//覆盖memmove(&(ps->a[pos]), &(ps->a[pos + 1]), sizeof(SLDataType) * (ps->size - pos - 1));ps->size--;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void TestSeqList1()//第一组测试用例
{SL s;SLInit(&s);SLPushBack(&s, 1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);SLPushBack(&s, 5);SLPushBack(&s, 6);SLPushBack(&s, 7);SLPushBack(&s, 8);SLPrint(&s);SLPopBack(&s);SLPopBack(&s);SLPrint(&s);SLPushFront(&s, 9);SLPushFront(&s, 10);SLPushFront(&s, 11);SLPushFront(&s, 12);SLPushFront(&s, 13);SLPushFront(&s, 14);SLPrint(&s);SLPopFront(&s);SLPopFront(&s);SLPopFront(&s);SLPrint(&s);SLInsert(&s, 3, 30);SLPrint(&s);SLErase(&s, 3);SLPrint(&s);int pos = SLFind(&s, 3);if (pos == -1){printf("没找到\n");}else{printf("找到了,下标是:%d", pos);}SLDestroy(&s);
}int main()
{TestSeqList1();return 0;
}

相关文章:

顺序表——C语言实现

目录 一、线性表 二、顺序表 1.实现动态顺序表 SeqList.h SeqList.c Test.c 问题 经验&#xff1a;free 出问题&#xff0c;2种可能性 解决问题 &#xff08;2&#xff09;尾删 &#xff08;3&#xff09;头插&#xff0c;头删 &#xff08;4&#xff09;在 pos 位…...

ARM 汇编启动代码详解:从中断向量表到中断处理

ARM 汇编启动代码详解&#xff1a;从中断向量表到中断处理 引言 在嵌入式系统开发中&#xff0c;ARM 处理器&#xff08;如 Cortex-A 系列&#xff09;的启动代码是系统初始化和运行的基础。启动代码通常包括中断向量表的创建、初始化硬件状态&#xff08;如关闭缓存和 MMU&a…...

LTSPICE仿真电路:(二十六)跨阻放大器简单仿真

1.前言 由于有个机会刚好了解了下跨阻&#xff0c;简单做个这个仿真&#xff0c;实际上跨阻放大器应该要复杂的多&#xff0c;由于跨阻放大器实际上是将电流转换为电压&#xff0c;最需要注意的参数肯定是运放的偏置电流 2.跨阻放大器仿真 这篇是纯记录 这是一个将0-50uA电流…...

特辣的海藻!15

题 1.迷宫 - 蓝桥云课 2.外卖店优先级 - 蓝桥云课 3.后缀表达式 - 蓝桥云课 题 1.迷宫 - 蓝桥云课 import java.util.*;public class Main {static class Node {int x;int y;String str;public Node(int x, int y, String str) {this.x x;this.y y;this.str str;} …...

RISCV GCC 后端 -- 依赖(Dependence)简析

在命令式语言&#xff0c;如C/C中&#xff0c;其依赖关系及分类如下&#xff1a; 依赖&#xff08;Dependence&#xff09; -- Control Dependence -- Data Dependence (Reads and Writes of the same location, registers / Memories etc) -- True Dependence (Write then Rea…...

算法-- js排序

汇总 注&#xff1a;以下log n 是 O(log2n) 注&#xff1a;快速排序实际应用中通常最优&#xff0c;但需避免最坏情况。 1 快速排序 [快速排序的思路] 分区&#xff1a;从数组中任意选择一个“基准”&#xff0c;所有比基准小的元素放在基准前面&#xff0c;比基准大的元素…...

FfreeRTOS有阻塞作用的API

在 FreeRTOS 中,阻塞 API 是指那些会导致调用任务进入阻塞状态(Blocked State)的函数,即任务会暂时让出 CPU,直到某个条件满足(如超时、信号量可用、队列数据到达等)。以下是常见的阻塞 API 分类及示例: 1. 任务延迟(延时) vTaskDelay() 使任务阻塞指定的时间(以系统…...

【棒垒球规则】全国幼儿软式棒垒球比赛规则(三)·棒球1号位

棒垒球球队的组成 3.01球队的组成 球队由教练员及工作人员 2 名至 4 名、队员 9 至 12 名组成。 球衣背号不大于两位数&#xff0c;背号不小于 15 厘米。 上场队员名单应填写上场选手和替补选手。 3.02防守位置及名称&#xff08;参照图四&#xff09; a&#xff0e;9 名队…...

stm32week10

stm32学习 七.CAN 7.STM32 CAN外设 标识符过滤器&#xff1a; 每个过滤器的核心由两个32位寄存器组成&#xff1a;R1[31:0]和R2[31:0] FSCx&#xff1a;位宽设置&#xff0c;置0为16位&#xff0c;置1为32位 FBMx&#xff1a;模式设置&#xff0c;置0为屏蔽模式&#xff0c;…...

Linux上历史命令显示时间,修改时间戳

今天分享一个生产环境避免背锅的小技巧&#xff1a;设置历史命令执行的具体时间。还可以快速定位问题出现的时间点并恢复误操作导致的系统问题&#xff0c;用于追踪溯源。 在Linux系统中&#xff0c;默认情况下&#xff0c;history命令只会显示命令的编号和命令内容&#xff0…...

看雪 get_pwn3(2016 CCTF 中的 pwn3)

get_pwn3(2016 CCTF 中的 pwn3) 格式化字符串漏洞 get_pwn3(2016 CCTF 中的 pwn3) (1) motalymotaly-VMware-Virtual-Platform:~/桌面$ file pwn3 pwn3: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, …...

python全栈-JavaScript

python全栈-js 文章目录 js基础变量与常量JavaScript引入到HTML文件中JavaScript注释与常见输出方式 数据类型typeof 显示数据类型算数运算符之加法运算符运算符之算术运算符运算符之赋值运算符运算符之比较运算符运算符之布尔运算符运算符之位运算符运算符优先级类型转换 控制…...

操作系统概述(3)

批处理系统 1.单道批处理系统 单道批处理系统是成批地处理作用&#xff0c;并且始终只有一道作业在内存中的系统。优点&#xff1a;提高系统资源的利用率和系统吞吐量。缺点&#xff1a;系统中的资源得不到充分利用。 2.多道批处理系统 引入多道程序设计技术&#xff0c;是…...

SolidWorks2025三维计算机辅助设计(3D CAD)软件超详细图文安装教程(2025最新版保姆级教程)

目录 前言 一、SolidWorks下载 二、SolidWorks安装 三、启动SolidWorks 前言 SolidWorks 是一款由法国达索系统&#xff08;Dassault Systmes&#xff09;公司开发的三维计算机辅助设计&#xff08;3D CAD&#xff09;软件&#xff0c;广泛用于机械设计、工程仿真和产品开…...

powershell绑定按钮事件的两种方式

写一个powershell的简单GUI做本地任务&#xff0c;试验出2个方法&#xff1a; 方法1&#xff1a; function btn1_click {write-host $text1.Text -ForegroundColor Green -BackgroundColor Black }$btn1.Add_Click({btn1_click})方法2&#xff1a; $btn2_click {write-host $…...

JBDC Java数据库连接(1)

目录 JDBC概述 定义 JDBC API 实例 JDBC搭建 建立与数据库连接&#xff1a; 形式&#xff1a; 实例 获得Satement执行sql语句 Satement中的方法: 实例 实例 JDBC概述 定义 JDBC&#xff08;Java DataBase Connectivity&#xff09;java数据库连接是一种用于执行SQL…...

Spring Boot 3.x 集成 MongoDB 的 默认配置项及默认值,以及 常用需要修改的配置项 的详细说明

以下是 Spring Boot 3.x 集成 MongoDB 的 默认配置项及默认值&#xff0c;以及 常用需要修改的配置项 的详细说明&#xff1a; 一、默认配置项及默认值 Spring Boot 对 MongoDB 的默认配置基于 spring.data.mongodb 前缀&#xff0c;以下是核心配置项&#xff1a; 配置项默认…...

git rebase复杂场景验证

经常面临复杂的分支管理&#xff0c;这里对几种场景的行为做一些验证。 结论总结 git rebase br_name&#xff1a;等价与新建br_name分支&#xff0c;然后找到当前分支与br_name分支的分叉点。然后把分叉点以后的提交&#xff08;当前分支&#xff09;一个一个的cherry-pick过…...

【Introduction to Reinforcement Learning】翻译解读2

2.2 马尔可夫决策过程&#xff08;MDPs&#xff09; 马尔可夫决策过程&#xff08;MDP&#xff09;为顺序决策提供了框架&#xff0c;其中动作不仅影响即时奖励&#xff0c;还会影响未来结果。与多臂老虎机问题不同&#xff0c;MDP中的即时奖励与延迟奖励相平衡。在多臂老虎机…...

大数据(5)Spark部署核弹级避坑指南:从高并发集群调优到源码级安全加固(附万亿级日志分析实战+智能运维巡检系统)

目录 背景一、Spark核心架构拆解1. 分布式计算五层模型 二、五步军工级部署阶段1&#xff1a;环境核弹级校验阶段2&#xff1a;集群拓扑构建阶段3&#xff1a;黄金配置模板阶段4&#xff1a;高可用启停阶段5&#xff1a;安全加固方案 三、万亿级日志分析实战1. 案例背景&#x…...

Linux内核中TCP协议栈的实现:tcp_close函数的深度剖析

引言 TCP(传输控制协议)作为互联网协议族中的核心协议之一,负责在不可靠的网络层之上提供可靠的、面向连接的字节流服务。Linux内核中的TCP协议栈实现了TCP协议的全部功能,包括连接建立、数据传输、流量控制、拥塞控制以及连接关闭等。本文将深入分析Linux内核中tcp_close…...

从搜索丝滑过渡到动态规划的学习指南

搜索&动态规划 前言砝码称重满分代码及思路solution 1&#xff08;动态规划&#xff09;solution 2&#xff08;BFS&#xff09; 跳跃满分代码及思路solution 1(动态规划)solution 2 (BFS) 积木画满分代码及思路动态规划思路讲解solution 前言 本文主要是通过一些竞赛真题…...

(一)栈结构、队列结构

01-线性结构-数组-栈结构 线性结构&#xff08;Linear List)是由n&#xff08;n>0)个数据元素&#xff08;结点&#xff09; a[0], a[1], a[2], a[3],...,a[n-1]组成的有限序列 数组 通常数组的内存是连续的&#xff0c;所以在知道数组下标的情况下&#xff0c;访问效率是…...

AWS SNS深度解析:构建高可用、可扩展的云原生消息通信解决方案

引言 在云原生架构中&#xff0c;高效的消息通信是系统解耦、实时响应的核心需求。AWS Simple Notification Service&#xff08;SNS&#xff09;作为一款全托管的发布/订阅&#xff08;Pub/Sub&#xff09;服务&#xff0c;为开发者提供了灵活、可靠的消息分发能力。本文将从…...

MySQL基础 [五] - 表的增删查改

目录 Create&#xff08;insert&#xff09; Retrieve&#xff08;select&#xff09; where条件 ​编辑 NULL的查询 结果排序(order by) 筛选分页结果 (limit) Update Delete 删除表 截断表&#xff08;truncate&#xff09; 插入查询结果&#xff08;insertselect&…...

4.7学习总结 可变参数+集合工具类Collections+不可变集合

可变参数&#xff1a; 示例&#xff1a; public class test {public static void main(String[] args) {int sumgetSum(1,2,3,4,5,6,7,8,9,10);System.out.println(sum);}public static int getSum(int...arr){int sum0;for(int i:arr){sumi;}return sum;} } 细节&#xff1a…...

OpenGL学习笔记(简介、三角形、着色器、纹理、坐标系统、摄像机)

目录 简介核心模式与立即渲染模式状态机对象GLFW和GLAD Hello OpenGLTriangle 三角形顶点缓冲对象 VBO顶点数组对象 VAO元素缓冲对象 EBO/ 索引缓冲对象 IEO 着色器GLSL数据类型输入输出Uniform 纹理纹理过滤Mipmap 多级渐远纹理实际使用方式纹理单元 坐标系统裁剪空间 摄像机自…...

vmware虚拟机上Ubuntu或者其他系统无法联网的解决方法

一、检查虚拟机是否开启了网络服务 打开方式&#xff1a;控制面板->-管理工具--->服务 查找 VMware DHCP Service 和VMware NAT Service &#xff0c;确保这两个服务已经启动。如下图&#xff0c;没有启动就点击启动。 二、设置网络类型 我们一般使用前两种多一些&…...

OpenVLA-OFT——微调VLA时加快推理的三大关键设计:支持动作分块的并行解码、连续动作表示以及L1回归(含输入灵活化及对指令遵循的加强)

前言 25年3.26日&#xff0c;这是一个值得纪念的日子&#xff0c;这一天&#xff0c;我司「七月在线」的定位正式升级为了&#xff1a;具身智能的场景落地与定制开发商 &#xff0c;后续则从定制开发 逐步过渡到 标准产品化 比如25年q2起&#xff0c;在定制开发之外&#xff0…...

Linux脚本基础详解

一、基础知识 Linux 脚本主要是指在 Linux 系统中编写的用于自动化执行任务的脚本程序&#xff0c;其中最常用的便是 Bash 脚本。下面我们将从语法、使用方法和示例三个方面详细讲解 Linux 脚本。 1. 脚本简介 定义&#xff1a;Linux 脚本是一系列命令的集合&#xff0c;可以…...