顺序表的代码实现

顺序表的代码实现

  • 1.认识什么是顺序表
    • 1.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 查找数据
  • 4.完整代码

1.认识什么是顺序表

  • 顺序表是一种基本的数据结构,属于线性表的一种具体实现形式。在顺序表中,数据元素被存储在计算机内存中的一系列连续的存储位置上,这些位置通常是由数组提供的。这意味着顺序表中的每个元素都占据一个固定的存储空间,并且可以通过其索引(或位置)直接访问。

总的来说:顺序表的底层是数组,是对数组的封装,实现了常用的增删改查等接口。因为底层是数组,所以在逻辑结构上一定是连续的,物理结构上不一定连续。

1.1顺序表的优缺点

顺序表的优缺点

2.实现顺序表代码准备

为了保持代码的清晰和模块化,在实现代码前我们需要定义三个文件:
SeqList.h:(函数的声明
1.这是一个头文件,它定义了顺序表的结构和对外提供的函数接口。
2.其他程序可以通过包含这个头文件来使用顺序表的功能。
3.头文件提供了一个清晰的接口文档,说明了如何使用顺序表,同时也隐藏了内部实现细节。
SeqList.c:(函数的实现
2.这是源文件,包含了顺序表的实际实现代码。
3.它实现了头文件中声明的所有函数。
Test.c:(测试函数的功能
1.这是一个测试文件,用来验证顺序表的正确性。
2.在这个文件中,你会写一些测试代码,调用顺序表的函数并检查结果是否符合预期。

3.顺序表的代码实现

在实现顺序表时需要用到的头文件:
<stdio.h>,<stdlib.h>,<assert.h>

  1. <stdio.h>
  • 用途:会使用 printf() 和 scanf() 等函数,用于控制台输出和输入。

  • 应用场景:

    • 在调试阶段,可以使用 printf() 来输出顺序表的状态,例如在插入、删除操作前后打印顺序表的内容。
    • 使用 scanf() 或者其他输入函数来从用户那里获取数据,例如插入新元素的值。
  1. <stdlib.h>
  • 用途:提供内存管理相关的函数,如 malloc(), calloc(), realloc(), 和 free()。
  • 应用场景:
    • 当需要扩展顺序表的容量时,可以使用 realloc() 来调整已分配内存的大小。
    • 当销毁顺序表时,使用 free() 来释放分配给 data 的内存。
  1. <assert.h>
  • 用途:在编译时检查条件是否为真,如果条件不满足,则会终止程序执行,并给出错误信息。
  • 应用场景:
    • 在函数入口处检查参数的有效性,例如在 SLInsert() 和 SLDelete() 函数中检查索引是否有效。

3.1 顺序表结构体的定义

  • SeqList.h中定义(动态)顺序表的基本数据结构
#include<stdio.h>
#include<stdlib.h>//开辟空间要用
#include<assert.h>//断言用
typedef int SLDataType;//重复定义int,便于修改顺序表中的顺序类型
typedef struct SeqList
{SLDataType* arr;//指向一块连续的空间int size;//顺序表的有效数据个数int capacity;//顺序表的可以容纳的数据容量个数
}SL://将结构体命名为SL,更加简洁,便于后期的创建

typedef int SLDataType;:这一行定义了一个类型别名SLDataType,它实际上就是int类型。这里使用类型别名是为了让数据结构更加通用和灵活,如果将来需要改变顺序表中元素的数据类型(比如从整型改为浮点型或者其他类型),只需要在这里修改SLDataType的定义即可,而不需要去修改整个数据结构的实现代码。

SLDataType* arr;:这是一个指向SLDataType类型的指针,代表了顺序表中存储数据的数组。arr指向的是一块连续的内存区域,这块区域可以存储多个SLDataType类型的元素。

int size;:定义一个整型变量,表示顺序表当前实际包含的元素数量。size的值不会超过capacity,并且在插入和删除元素时会相应地增减。

int capacity;:一个整型变量,表示顺序表当前的容量,即arr所指向的数组能容纳的最大元素数量。capacity反映了顺序表当前分配的内存大小,当size接近capacity时,以便重新分配更大的内存空间以避免溢出。

3.2 顺序表的初始化

  • 先在SeqList.h中声明初始化函数SLInit,然后在SeqList.c中实现对顺序表的初始化,定义一个初始化函数SLInit,将data初始化为空NULL,将有效数据个数size和顺序表大小capacity初始化为0;

.h文件中声明:

// 声明初始化顺序表的函数
void SLInit(SeqList *list);

.c文件中实现:

//顺序表的初始化
void SLInit(SL* ps)
{ps->a = NULL;ps->size = ps->capacity = 0;
}

test文件中测试

#include "SeqList.h"
void SLTest01()
{SL sl;SLInit(&sl);//初始化
}
int main()
{SLTest01();return 0;
}

调试

3.3 顺序表的销毁

  • 先在.h文件中声明销毁函数,然后在.c文件中实现,销毁通常是释放分配给顺序表的内存,如将data指针指向的内存释放,并将其置为空。

.h中声明:

// 声明销毁顺序表的函数
void SLDestroy(SeqList *ps);

.c中实现:

//销毁
void SLDestroy(SL* ps)if (ps->a)//判断顺序表(数组)是否为空;等价于(ps->a != NULL){free(ps->a);//若不为空,则释放内存}ps->a = NULL;//释放内存后置空ps->size = ps->capacity = 0;
}

test中测试

#include "SeqList.h"
void SLTest01()
{SL sl;SLInit(&sl);//初始化SLDestroy(&sl);//销毁
}int main()
{SLTest01();return 0;
}

销毁测试

3.4 顺序表的输出打印

  • 遍历顺序表,打印顺序表数据:
//顺序表的打印
void SLPrint(SL ps)
{for (int i = 0; i < ps.size; i++){printf("%d ",ps.a[i]);}printf("\n");
}

3.5顺序表的扩容

  • 在插入数据时,要保证顺序表的空间足够,否则就要对顺序表进行扩大,以保证插入操作的有效性,所以定义SLCheckCapacity函数对顺序表的大小进行检查,以便及时对空间大小进行调整。

.h中声明:

//扩容
void SLCheckCapacity(SL* ps);

.c中实现:

void SLCheckCapacity(SL* ps)//检查空间是否足够
{if (ps->capacity == ps->size)//若不够,则动态开辟内存{int newCapacity = ps->capacity == 0 ? INIT_CAPACITY : 2 * ps->capacity;//创建临时变量newCapacity来开辟内存,保证a不会因为realloc开辟失败返回空,导致a的数据丢失SLDataType* temp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));if (temp == 0){perror("realloc error!");//内存开辟失败的提示return 1;//退出程序}//开辟内存成功ps->a = temp;//确保内存开辟成功后赋值给aps->capacity = newCapacity;//更新空间大小}
}

3.6 顺序表的头部插入(头插)

  1. 函数首先检查传入的指针 ps 是否为 NULL。如果是 NULL,则触发断言失败,程序终止。防止对无效指针进行操作。
  2. 然后,调用 SLCheckCapacity 函数来确保顺序表有足够的空间来容纳新插入的元素。如果空间不足,则调整数组的大小。
  3. 接着,使用一个循环从最后一个元素开始,将每个元素向后移动一个位置。循环条件是从
    ps->size(有效数据个数)到 1。每次循环时,ps->a[i] 的值被赋值给 ps->a[i + 1],将所有元素都向后移动了一位,腾出 ps->a[0] 这个位置。
  4. 将新元素 x 放在 ps->a[0] 的位置上,进行头插。
  5. 插入元素后,更新元素总数,数量增加 1,即 ps->size 的值加 1

.h中声明:

//头插
void SLPushFront(SL* ps, SLDataType x);

.c中实现:

//头插
void SLPushFront(SL* ps, SLDataType x)//头插
{assert(ps);SLCheckCapacity(ps);//判断数组(顺序表)大小是否足够//让顺序表中原来的数据整体向后移动一位for (int i = ps->size - 1; i >= 0; i--){ps->a[i + 1] = ps->a[i];//ps->a[1] = ps->a[0]}ps->a[0] = x;ps->size++;//头插后,顺序表中数据个数有所变化,所以需要++更新
}

3.7 顺序表的头部删除(头删)

  1. 参数检查:
    • 检查传入的指针 ps 是否为 NULL。如果是 NULL,断言失败,防止对无效指针进行操作。
    • 接着检查 ps->size 是否大于 0,即顺序表中是否有元素可以删除。如果没有元素,则断言失败,防止从空顺序表中删除元素。
  2. 元素移动:
    • 使用一个循环从第一个元素开始,将每个元素向前移动一个位置。循环条件是从 0
      ps->size - 2。每次循环时,ps->a[i + 1] 的值被赋值给 ps->a[i]。这样就能将所有元素都向前移动了一位,覆盖了原本位于 ps->a[0] 的元素,实现了头删操作。
  3. 更新大小:
    • 删除元素后,顺序表中的元素总数减少 1,因此 ps->size 的值减 1

.h中声明:

void SLPopFront(SL* ps);//头删

.c中实现:

//头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);//最前面的数据删除后,后面的数据整体向前挪一位for (int i = 0; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];//arr[size - 2] = arr[size - 1]}ps->size--;//删除后对有效数据进行更新
}

test中测试:
在这里插入图片描述

3.8 顺序表的尾部插入(尾插 )

  1. 参数检查:
    • assert(ps) 确保传入的指针 ps 不为 NULL。如果 ps 为 NULL,则断言失败,程序会终止。
  2. 容量检查:
    • 调用 SLCheckCapacity(ps) 函数来确保顺序表有足够的空间来容纳新插入的元素。如果空间不足,SLCheckCapacity 会调整数组的大小。
  3. 插入新元素:
    • 使用 ps->a[ps->size++] = x;,将新元素 x 插入到数组 ps->a 的当前有效大小的位置,也就是数组的最后一个位置。最后,ps->size 的值加 1,更新顺序表中元素数量的变化。

.h中声明:

//尾插
void SLPushBack(SL* ps, SLDataType x);

.c中是实现:

//尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//判断数组(顺序表)大小是否足够ps->a[ps->size++] = x;//尾插数据,并更新有效数据的个数//ps->a[ps->size] = x;//ps->size++;
}

3.9 顺序表的尾部删除(尾删)

  1. 参数检查:
    • 使用 assert(ps) 确保传入的指针 ps 不为 NULL。如果 ps 为 NULL,则断言失败,导致程序终止。
    • 使用 assert(ps->size) 确保顺序表中至少有一个元素。如果 ps->size 为 0,说明顺序表为空,无法删除元素,也会断言失败。
  2. 删除元素:
    • 由于顺序表是通过数组实现的,删除尾部元素的操作非常简单,只需将 ps->size 减少 1 即可。
    • 在 C 语言中,数组的索引是从 0 开始的,因此 ps->a[ps->size - 1] 表示顺序表中的最后一个元素。
    • 删除最后一个元素后,ps->size 应该减 1,更新顺序表中有效的数据个数。
  3. 清理尾部元素(理解即可):
    • 代码注释中将最后一个元素置为 -1,但这不是必需的。因为 ps->size 已经减少了 1,所以 ps->a[ps->size](即原本的 ps->a[ps->size - 1])不再是有效索引,即使保留原有的值也不会影响后续的操作。
    • 因此,代码中并没有执行 ps->a[ps->size - 1] = -1; 这一行,而是直接减少 ps->size 的值。

.h中声明:

void SLPopBack(SL* ps);//尾删

.c中实现:

//尾删
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);//assert断言,确保顺序表不能为空(顺序表不为空,顺序表中的有效数据size也不为空)//ps->a[size - 1] = -1;//尾删的数据不论是否置为-1,都不影响增删查改ps->size--;
}

test中测试:
尾插尾删测试

3.10 在指定位置之前插入数据

  1. 参数检查:
    • 使用 assert(ps) 确保传入的指针 ps 不为 NULL。如果 ps 为 NULL,则断言失败,导致程序终止。
    • 使用 assert(pos >= 0 && pos <= ps->size) 确保指定的插入位置 pos 是有效的。位置 pos 必须是非负的,并且不能超过当前顺序表的有效大小 ps->size。
  2. 容量检查:
    • 调用 SLCheckCapacity(ps) 函数来确保顺序表有足够的空间来容纳新插入的元素。如果空间不足,SLCheckCapacity 会调整数组的大小以满足插入需求。
  3. 元素移动:
    • 使用一个循环从最后一个有效元素开始,将每个元素向后移动一个位置,直到达到目标位置 pos。
    • 循环条件是从 ps->size 到 pos,即 for (int i = ps->size; i > pos; i–)。将所有在 pos 之后的元素都向后移动一位,为新元素腾出空间。
  4. 插入新元素:
    • 将新元素 x 插入到 ps->a[pos] 的位置,即指定的位置。
  5. 更新大小:
    • 插入元素后,顺序表中的元素总数增加 1,更新ps->size 的值加 1。

.h中声明:

//指定位置插入
void SLInsert(SL* ps, int pos, SLDataType x);

.c中实现:

//指定位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//插入数据,判断空间够不够SLCheckCapacity(ps);//让数据整体向后挪一位for (int i = ps->size;i >pos;i--){ps->a[i] = ps->a[i - 1];//a[pos + 1] = a[pos];}ps->a[pos] = x;ps->size++;
}

test中测试:
指定位置前插入测试

3.11 删除指定位置的数据

  1. 参数检查:
    • 使用 assert(ps) 确保传入的指针 ps 不为 NULL。如果 ps 为 NULL,则断言失败,导致程序终止。
    • 使用 assert(pos >= 0 && pos < ps->size) 确保指定的删除位置 pos 是有效的。位置 pos 必须是非负的,并且不能超过当前顺序表的有效大小 ps->size。
  2. 元素移动:
    • 使用一个循环从指定位置 pos 开始,将每个元素向前移动一个位置,直到达到顺序表的倒数第二个元素。
    • 循环条件是从 pos 到 ps->size - 1,即 for (int i = pos; i < ps->size - 1; i++)。将所有在 pos 之后的元素都向前移动一位,覆盖被删除元素的位置。
  3. 更新大小:
    删除元素后,顺序表中的元素总数减少 1,更新ps->size 的值减 1。
    .h中声明:
void SLErase(SL* ps, int pos);//指定位置删除

.c中实现:

//指定位置删除数据
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps-> size - 1;i++){//删除后后面的数据向前挪一位ps->a[i] = ps->a[i + 1];//a[size - 2] = a[size - 1];}ps->size--;
}

test中测试:
指定位置删除测试

3.12 查找数据

  1. 参数检查:
    • 使用 assert(ps) 确保传入的指针 ps 不为 NULL。如果 ps 为 NULL,则断言失败,导致程序终止。
  2. 遍历顺序表:
    • 使用一个循环从顺序表的第一个元素开始遍历整个顺序表。
    • 循环条件是从 0 到 ps->size - 1,即 for (int i = 0; i < ps->size; i++)。因为 ps->size 表示顺序表中有效元素的数量,所以有效元素的索引范围是从 0 到 ps->size - 1。
  3. 比较数据:
    • 在循环体内,使用 if (ps->a[i] == x) 来检查当前元素 ps->a[i] 是否等于要查找的数据 x。
    • 如果找到匹配的元素,则返回该元素的下标 i。
  4. 未找到数据:
    • 如果循环结束后都没有找到匹配的数据,函数返回 -1,表示数据 x 不在顺序表中。

.h中声明:

int SLFind(SL* ps, SLDataType x);//指定位置查找

.c中实现:

//查找数据
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){//找到了if (ps->a[i] == x){return i;}}return -1;//返回一个无效下标,习惯上返回-1;
}

test中测试:
查找数据测试

4.完整代码

SeqList.h文件:

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>#define INIT_CAPACITY 4typedef int SLDataType;
// 动态顺序表 -- 按需申请
typedef struct SeqList
{SLDataType* a;int size;     // 有效数据个数int capacity; // 空间容量
}SL;//初始化和销毁
void SLInit(SL* ps);//初始化
void SLDestroy(SL* ps);//销毁void SLPrint(SL ps);//顺序表的打印//扩容
void SLCheckCapacity(SL* ps);//头部插入删除 / 尾部插入删除
void SLPushBack(SL* ps, SLDataType x);//尾插
void SLPopBack(SL* ps);//尾删
void SLPushFront(SL* ps, SLDataType x);//头插
void SLPopFront(SL* ps);//头删//指定位置之前插入/删除数据
void SLInsert(SL* ps, int pos, SLDataType x);//指定位置插入
void SLErase(SL* ps, int pos);//指定位置删除
int SLFind(SL* ps, SLDataType x);//指定位置查找

SeqList.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"void SLInit(SL* ps)//顺序表的初始化
{ps->a = NULL;ps->size = ps->capacity = 0;
}void SLCheckCapacity(SL* ps)//检查空间是否足够
{if (ps->capacity == ps->size)//若不够,则动态开辟内存{int newCapacity = ps->capacity == 0 ? INIT_CAPACITY : 2 * ps->capacity;//创建临时变量newCapacity来开辟内存,保证a不会因为realloc开辟失败返回空,导致a的数据丢失SLDataType* temp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));if (temp == 0){perror("realloc error!");//内存开辟失败的提示return 1;//退出程序}//开辟内存成功ps->a = temp;//确保内存开辟成功后赋值给aps->capacity = newCapacity;//更新空间大小}
}//尾插
void SLPushBack(SL* ps, SLDataType x)
{assert(ps);SLCheckCapacity(ps);//判断数组(顺序表)大小是否足够ps->a[ps->size++] = x;//尾插数据,并更新有效数据的个数//ps->a[ps->size] = x;//ps->size++;
}//头插
void SLPushFront(SL* ps, SLDataType x)//头插
{assert(ps);SLCheckCapacity(ps);//判断数组(顺序表)大小是否足够//让顺序表中原来的数据整体向后移动一位for (int i = ps->size - 1; i >= 0; i--){ps->a[i + 1] = ps->a[i];//ps->a[1] = ps->a[0]}ps->a[0] = x;ps->size++;//头插后,顺序表中数据个数有所变化,所以需要++更新
}//尾删
void SLPopBack(SL* ps)
{assert(ps);assert(ps->size);//assert断言,确保顺序表不能为空(顺序表不为空,顺序表中的有效数据size也不为空)//ps->a[size - 1] = -1;//尾删的数据不论是否置为-1,都不影响增删查改ps->size--;
}//头删
void SLPopFront(SL* ps)
{assert(ps);assert(ps->size);//最前面的数据删除后,后面的数据整体向前挪一位for (int i = 0; i < ps->size - 1; i++){ps->a[i] = ps->a[i + 1];//arr[size - 2] = arr[size - 1]}ps->size--;//删除后对有效数据进行更新
}//顺序表的打印
void SLPrint(SL ps)
{for (int i = 0; i < ps.size; i++){printf("%d ",ps.a[i]);}printf("\n");
}void SLDestroy(SL* ps)//销毁
{if (ps->a)//判断顺序表(数组)是否为空;等价于(ps->a != NULL){free(ps->a);//若不为空,则释放内存}ps->a = NULL;//释放内存后置空ps->size = ps->capacity = 0;
}//指定位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps);assert(pos >= 0 && pos <= ps->size);//插入数据,判断空间够不够SLCheckCapacity(ps);//让数据整体向后挪一位for (int i = ps->size;i >pos;i--){ps->a[i] = ps->a[i - 1];//a[pos + 1] = a[pos];}ps->a[pos] = x;ps->size++;
}//指定位置删除数据
void SLErase(SL* ps, int pos)
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i < ps-> size - 1;i++){//删除后后面的数据向前挪一位ps->a[i] = ps->a[i + 1];//a[size - 2] = a[size - 1];}ps->size--;
}//查找数据
int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; i++){//找到了if (ps->a[i] == x){return i;}}return -1;//返回一个无效下标,习惯上返回-1;
}

Test.c文件:

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
void SLTest01()
{SL sl;SLInit(&sl);//初始化//增删查改操作头插测试//SLPushFront(&sl, 0);//SLPrint(sl);//SLPushFront(&sl, 2);//SLPrint(sl);//SLPushFront(&sl, 5);//SLPrint(sl);//头删测试//SLPopFront(&sl);//SLPrint(sl);//SLPopFront(&sl);//SLPrint(sl);//SLPopFront(&sl);//SLPrint(sl);//尾插测试SLPushBack(&sl, 1);SLPrint(sl);SLPushBack(&sl, 3);SLPrint(sl);SLPushBack(&sl, 1);SLPrint(sl);SLPushBack(&sl, 4);	SLPrint(sl);//尾删测试//SLPopBack(&sl);//SLPrint(sl);//SLPopBack(&sl);//SLPrint(sl);//SLPopBack(&sl);//SLPrint(sl);//SLPopBack(&sl);//SLPrint(sl);printf("\n");//指定位置插入测试SLInsert(&sl, 0, 520);SLPrint(sl);SLInsert(&sl, 5, 20);SLPrint(sl);SLInsert(&sl, 2, 1314);SLPrint(sl);//指定位置删除测试SLErase(&sl, 0);SLPrint(sl);SLErase(&sl, 2);SLPrint(sl);SLErase(&sl, 1);SLPrint(sl);//顺序表查找数据int find = SLFind(&sl, 40);if (find >= 0){printf("找到了!下表为%d\n",find);}else{printf("没找到!");}SLDestroy(&sl);//销毁
}int main()
{SLTest01();return 0;
}

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

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

相关文章

2种常用的取消word文档”打开密码“方法

在日常工作中&#xff0c;我们有时会遇到需要取消Word文档“打开密码”的情况。无论是因为忘记密码&#xff0c;还是出于文档共享的需要&#xff0c;掌握几种有效的取消密码方法都显得尤为重要。以下是2种常用的方法来取消Word文档的“打开密码”。 方法一&#xff1a;文件另存…

二叉树--堆(上卷)

二叉树–堆&#xff08;上卷&#xff09; 树 树的概念与结构 树是⼀种⾮线性的数据结构&#xff0c;它是由 n&#xff08;n>0&#xff09; 个有限结点组成⼀个具有层次关系的集合。把它叫做 树是因为它看起来像⼀棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;⽽…

智慧医院信息系统思维导图

智慧医院信息系统 "思维导图智慧医院信息系统, 用一张图解析智慧医疗信息系统 本文转载&#xff1a;有了这个智慧医院信息系统思维导图&#xff0c;没人不明医疗信息化

是时候学习Grid布局了

一、序言 先说什么&#xff1f;当然先说大家最关心的兼容性了 CanIUse 嗯&#xff0c;对于非要兼容IE的开发者&#xff0c;我建议&#xff0c;量力而行&#xff01;兼容性还是不如Flex 当然&#xff0c;如果你flex够熟悉了&#xff0c;但却被一些布局有时候难倒&#xff0c;我…

学习react-登录状态验证

1.创建三个页面LoginPage, HomePage,NotFoundPage用于Router 创建LoginPage.tsx用于做登录页面 // LoginPage.tsx const LoginPage (props:LoginProp) > {const navigate useNavigate();return( <h1 onClick{ ()>{navigate("/");}}>Hello Login, {pr…

昇思25天学习打卡营第1天 | 快速入门教程

昇思大模型平台&#xff0c;就像是AI学习者和开发者的超级基地&#xff0c;这里不仅提供丰富的项目、模型和大模型体验&#xff0c;还有一大堆经典数据集任你挑。 AI学习有时候就像找不到高质量数据集的捉迷藏游戏&#xff0c;而且本地跑大数据集训练模型简直是个折磨&#xf…

JQuery简单实现ul li点击菜单项被选中的菜单项保持高亮状态(导航ul li点击切换样式)

效果&#xff1a; JS&#xff1a; $(function () {//遍历list&#xff08;一般为ul li&#xff09;$("#menu a").each(function () {//给当前项添加点击事件&#xff08;点击后切换样式&#xff09;$(this).bind(click,function () {// 移除其他所有项的active类$(&…

挑战房市预测领头羊:KNN vs. 决策树 vs. 线性回归

挑战房市预测领头羊&#xff08;KNN&#xff0c;决策树&#xff0c;线性回归&#xff09; 1. 介绍1.1 K最近邻&#xff08;KNN&#xff09;&#xff1a;与邻居的友谊1.1.1 KNN的基础1.1.2 KNN的运作机制1.1.3 KNN的优缺点 1.2 决策树&#xff1a;解码房价的逻辑树1.2.1 决策树的…

【日常设计案例分享】通道对账

今天跟同事们讨论一个通道对账需求的技术设计。鉴于公司业务线有好几个&#xff0c;为避免不久的将来各业务线都重复竖烟囱&#xff0c;因此&#xff0c;我们打算将通道对账做成系统通用服务&#xff0c;以降低各业务线的开发成本。 以下文稿&#xff08;草图&#xff09;&…

局部变量,在使用时再定义

关于局部变量&#xff0c;适时定义局部变量&#xff0c;可提高代码清晰度和可读性&#xff0c;并能规避不必要的代码bug 局部变量&#xff0c;在使用时再定义&#xff0c;提高代码可读性 下面代码中的2个方法&#xff0c;第1个 verifyTaskApply 调用第2个 existAppliedTask 。…

20240730 每日AI必读资讯

&#x1f3ac;燃爆&#xff01;奥运8分钟AI影片火了&#xff0c;巴赫主席&#xff1a;感谢中国黑科技 - 短片名为《永不失色的她》&#xff08;To the Greatness of HER&#xff09;&#xff0c;由阿里巴巴和国际奥委会联合推出。 - 百年奥运史上伟大女性的影响故事在此被浓缩…

Rust语言入门第七篇-控制流

文章目录 Rust语言入门第七篇-控制流If 表达式基本结构特点和规则示例 let 语句中使用 ifloop 循环基本结构特点示例综合示例 while 循环基本结构特点示例综合示例 与 loop 循环的区别 for 循环基本结构详细说明特点示例综合示例 Rust语言入门第七篇-控制流 Rust 的控制流是指…

Oracle Database 23.5 - for Engineered Systems版本发布

要尝鲜的可以在https://edelivery.oracle.com/下载。对于x86的本地版本再等等吧。 安装可参考飞总的&#xff1a;oracle 23ai&#xff08;23.5.0.24.07&#xff09;完整功能版安装体验 – 提供7*24专业数据库(Oracle,SQL Server,MySQL,PostgreSQL等)恢复和技术支持Tel:1781323…

Python数值计算(12)

本篇说说Neville方法。Neville方法的基础是&#xff0c;插值多项式可以递归的生成&#xff0c;有时进行插值的目的是为了计算某个点的值&#xff0c;这个时候并不需要将拟合曲线完全求出&#xff0c;而是可以通过递归的方式进行计算&#xff0c;具体操作如下&#xff1a; 例如…

OpenGL学习 1

一些唠叨&#xff1a; 很多时候&#xff0c;都被Live2d吸引&#xff0c;去年想给网页加个live2d看板娘&#xff0c;结果看不懂live2d官方给的SDK&#xff0c;放弃了。今天又想弄个live2d桌宠&#xff0c;都已经在网上找到Python 的 Live2D 拓展库了&#xff0c;并提供了用QT实现…

昇思25天学习打卡营第19天|ResNet50 图像分类案例:数据集、训练与预测可视化

目录 环境配置 数据集加载 数据集可视化 Building Block Bottleneck 构建ResNet50网络 模型训练与评估 可视化模型预测 环境配置 首先指出实验环境预装的 mindspore 版本以及更换版本的方法。然后&#xff0c;它卸载了已安装的 mindspore 并重新安装指定的 2.3.0rc1 版本…

值得买科技与MiniMax达成官方合作伙伴关系,共建融合生态

7月29日&#xff0c;值得买科技与大模型公司MiniMax宣布达成官方合作伙伴关系。 MiniMax旗下大模型产品海螺AI现已接入值得买“消费大模型增强工具集”&#xff0c;基于海螺AI比价策略&#xff0c;用户可通过海螺AI“悬浮球”功能实现快速比价及跳转购买。 此次合作也标志着值…

操作系统重点总结

文章目录 1. 操作系统重点总结1.1 操作系统简介1.1.1 操作系统的概念和功能1.1.2 操作系统的特征1.1.2.1 并发1.1.2.2 共享1.1.2.3 虚拟1.1.2.4 异步 1.1.3 操作系统的发展与分类1.1.4 中断和异常1.1.5 系统调用1.1.6 操作系统的体系结构1.1.7 操作系统简介总结 1.2 进程1.2.1 …

使用YApi平台来管理接口

快速上手 进入YApi官网&#xff0c;进行注册登录https://yapi.pro/添加项目 3. 添加分类 4. 添加接口 5. 添加参数 添加返回数据 可以添加期望 验证 YAPI&#xff08;Yet Another Practice Interface&#xff09;是一个现代化的接口管理平台&#xff0c;由淘宝团队…

企业邮箱如何进行邮件监控

企业邮箱监控保障资产安全、合规性&#xff0c;防范网络攻击&#xff0c;提升员工行为。核心要素包括内容扫描、行为分析、合规性检查等。实施策略涉及技术选择、政策制定、员工培训。企业邮箱如何进行邮件监控呢&#xff1f;Zoho邮箱的eDiscovery功能可实现长期邮件保存和监控…