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

顺序表整理和单项链表01 day20

二:各个主要函数

一:CreatSeqList

SeqList *CreateSeqList(int len);
-------------------------------------------------------------/*** @brief Create a Seq List object  创建一个顺序表** @param n 是顺序表的大小* @return SeqList*  指向顺序表的指针 (重要) ,错误的话返回NULL*/
SeqList *CreateSeqList(int n)
{SeqList *sl = malloc(sizeof(SeqList));if (sl == NULL){fprintf(stderr,"CreateSeqList malloc error\n");  // strerr 专门输出错误信息的return NULL;}sl->head = malloc(sizeof(DATATYPE) * n);if (NULL == sl->head){fprintf(stderr,"CreateSeqList malloc2 error\n");  // strerr 专门输出错误信息的return NULL;}sl->tlen = n;sl->clen = 0;return sl;
}

作用:创建一个顺序表,最多可存储 len 个元素。

返回值:创建好的顺序表指针。

二:DestroySeqList

`int DestroySeqList(SeqList *list);`

作用:销毁顺序表,释放所有内存

三:ShowSeqList

int ShowSeqList(SeqList *list);

作用:遍历顺序表,将所有元素打印出来

四:InsertTailSeqList

int InsertTailSeqList(SeqList *list, DATATYPE data);

作用:将一个元素插入到顺序表末尾。

五:IsFullSeqList

int IsFullSeqList(SeqList *list);

作用:判断顺序表是否已满

返回值

  • 1 表示已满。
  • 0 表示未满。

六:IsEmptySeqList

int IsEmptySeqList(SeqList *list);
--------------------------------------------------------
int IsEmptySeqList(SeqList* sl)
{return 0 == sl->clen;
}

作用:判断顺序表是否为空。

返回值

  • 1 表示为空。
  • 0 表示非空。

七:InsertPosSeqList

int InsertPosSeqList(SeqList *list, DATATYPE data, int pos);

作用:将一个元素插入到指定位置 pos

关键点

  • 判断是否满。
  • 判断位置是否有效。
  • 从尾部开始向后移动,腾出空间。
  • 插入元素到 pos
  • len++

八:FindSeqList

int FindSeqList(SeqList *list, char *name);
---------------------------------------------

作用:在顺序表中查找名字为 name 的元素

返回值

  • 找到则返回该元素的索引(下标)。
  • 未找到返回 -1

九:ModifySeqList

int ModifySeqList(SeqList *list, char *old, DATATYPE new);

作用:将名字为 old 的元素替换为 new

流程

  • 调用 FindSeqList 查找旧元素。
  • 替换内容。

十:DeleteSeqList

int DeleteSeqList(SeqList *list, char *name);

作用:删除名字为 name 的元素。

流程

  • 找到该元素的下标。
  • 用后面的元素依次向前覆盖。
  • len--

十一:ClearSeqList

int ClearSeqList(SeqList *list);

作用:清空顺序表中所有元素,但不释放内存。

等效于list->len = 0;

三:线性表(升级版的数组)

一:基础定义

1.线性表:零个或多个数据元素的有限序列

线性表元素的个数n(n≥0)定义为线性表的长度,当n=0时,称为空表

线性表的数据对象集合为{a1,a2.....an),每个元素的类型均为DataType。其中,除第一个元素a外,每一个元素有且只有一个直接前驱元素,除了最后一个元素a,外,每一个元素有且只有一个直接后继元素。数据元素之间的关系是一对一的关系

​ 元素之间是有顺序了。如果存在多个元素,第一个元素无前驱,最有一个没有后继,其他的元素只有一个前驱和一个后继。
​ 当线性表元素的个数n(n>=0)定义为线性表的长度,当n=0时,为空表。在非空的表中每个元素都有一个确定的位置,如果a1是第一个元素,那么an就是第n个元素。

线性表顺序存储的优点,缺点
优点
1,无需为表中的逻辑关系增加额外的存储空间
2,可以快速随机访问元素O(1)
缺点
1,插入,删除元素需要移动元素o(n)
2,无法动态存储。

二:线性表的顺序存储结构

1.为了建立一个线性表,要在内存中找一块地,于是这块地的第一个位置就非常关键,它是存储空间的起始位置。

2.顺序存储结构需要三个属性:存储空间的起始位置:数组data,它的存储位置就是存储空间的存储位置。

​ 线性表的最大存储容量:数组长度MaxSize

​ 线性表的当前长度:length。

三:memcpy()

void *memcpy(void *str1, const void *str2, size_t n)

参数:

  • str1 – 指向用于存储复制内容的目标数组,类型强制转换为 void* 指针。
  • str2 – 指向要复制的数据源,类型强制转换为 void* 指针。
  • n – 要被复制的字节数。

返回值:该函数返回一个指向目标存储区 str1 的指针。

memcpy(&sl->head[sl->clen], data, sizeof(DATATYPE));
//练习InsertPosSeqList
//由于顺序表的原因,当旧数据和clen一样大时,无法插入新数据
//当旧数据比clen小至少2个数据时,新数据不能直接插入最后一位的位置
//当新数据插入旧数据时,且当旧数据比clen小至少1个数据时,
//新数据前的旧数据不变位置,新数据后的旧数据由于新数据的插入,向后顺延一个数据的位置

四::顺序表(Seqlist

1.组成

Head组头:Head[0]—Head[1]--------------Head[n]·

Tlen:总长度

Clen:当前长度

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

DATATYPE * Head

理解:就是head,tlen,clne三个组成结构体,其中clen是我所设的数组a的长度大小(a[clen] = {...,.,.}),其中tlen就是所设数组a[clen] = {...,.,.}中存放的有效元素个数,所以head这个一位数组(指针变量)可以指向数组a[clen] = {...,.,.}中存放的有效元素。clen限制所设数组长度,tlen存放有效元素个数,head访问有效元素,head的长度应该<=clen

SeqList *CreateSeqList(int len);
int DestroySeqList(SeqList *list);//销毁
int ShowSeqList(SeqList *list);//展示
int InsertTailSeqList(SeqList *list, DATATYPE data);//尾插
int IsFullSeqList(SeqList *list);//判断是否满
int IsEmptySeqList(SeqList *list);//判断是否空
int InsertPosSeqList(SeqList *list, DATATYPE data, int pos);//按位置插
int FindSeqList(SeqList *list, char *name);//查找
int ModifySeqList(SeqList *list, char *old, DATATYPE new);//修改
int DeleteSeqList(SeqList *list, char *name);//删除
int ClearSeqList(SeqList *list);//清空表
//.h文件
#ifndef  _SEQLIST_H_
#define  _SEQLIST_H_typedef struct  
{char name[32];char sex;int age;int score;}PER;typedef PER DATATYPE;
typedef struct 
{DATATYPE * head; // 数组的数组名   存储datatype 类型的数据int tlen;       // 数组的容量int clen;       // 数组中有效元素的个数
}SeqList;// 顺序表 表头结构SeqList* CreateSeqList(int n);
int InsertTailSeqList(SeqList* sl,DATATYPE*data);
int ShowSeqList(SeqList* sl);
int IsFullSeqList(SeqList* sl);
int GetSizeSeqList(SeqList* sl);
int InsertPosSeqList(SeqList *sl, DATATYPE *data, int pos);#endif 
----------------------------------------------------------------------------------------------------------//.c文件
SeqList *CreateSeqList(int n)
{SeqList *sl = malloc(sizeof(SeqList));//malloc 是动态内存分配函数,用于在堆(Heap)上申请一块连续的内存空间sizeof(SeqList) 计算 SeqList 结构体的大小(字节数),确保分配的内存足够存储整个结构体。//SeqList *sl:定义一个指向 SeqList 结构体的指针 sl。将 malloc 返回的内存地址赋值给 sl,此时 sl 指向新分配的内存空间。//直接定义 SeqList sl 会创建在栈(Stack)上,但顺序表通常需要动态调整大小(如扩容),因此需通过堆内存动态分配。if (NULL == sl){fprintf(stderr,"CreateSeqList malloc error\n");  // strerr 专门输出错误信息的return NULL;}sl->head = malloc(sizeof(DATATYPE) * n);if (NULL == sl->head){fprintf(stderr,"CreateSeqList malloc2 error\n");  // strerr 专门输出错误信息的return NULL;}sl->tlen = n;sl->clen = 0;return sl;
}
/*** @brief  顺序表的尾插** @param sl 被插入的 顺序表* @param data 被存储的数据的指针* @return int  0表示成功 1 表示失败*/
int InsertTailSeqList(SeqList *sl, DATATYPE *data)
{if (IsFullSeqList(sl)){return 1;}// strcpymemcpy(&sl->head[sl->clen], data, sizeof(DATATYPE));sl->clen++;return 0;
}int InsertPosSeqList(SeqList *sl, DATATYPE *data, int pos)
{if (sl == NULL || data == NULL){fprintf(stderr, "Error: NULL pointer!\n");return -1;  // 返回错误码}if (sl->clen >= sl->tlen){fprintf(stderr, "Error: SeqList is full!\n");return -1;}if (pos > sl->clen || pos < 0){fprintf(stderr,"CreateSeqList malloc2 error\n");  // strerr 专门输出错误信息的}if (pos < sl->clen){for (int i = sl->clen; i > pos; i--){memcpy(&sl->head[i], &sl->head[i - 1], sizeof(DATATYPE));}}memcpy(&sl->head[pos], data, sizeof(DATATYPE));sl->clen++;return 0;
}
/*** @brief 遍历整个顺序表** @param sl 被遍历的顺序表的指针* @return int 0表示成功 1 表示失败*/
int ShowSeqList(SeqList *sl)
{int size = GetSizeSeqList(sl);int i = 0;for (i = 0; i < size; i++){printf("name:%s sex:%c age:%d score:%d\n", sl->head[i].name,sl->head[i].sex, sl->head[i].age, sl->head[i].score);}return 0;
}int IsFullSeqList(SeqList *sl) { return sl->clen == sl->tlen; }
int GetSizeSeqList(SeqList *sl) { return sl->clen; }

4-1:完整seqlist练习

//.h文件#ifndef  _SEQLIST_H_
#define  _SEQLIST_H_typedef struct  
{char name[32];char sex;int age;int score;}PER;typedef PER DATATYPE;
typedef struct 
{DATATYPE * head; // 数组的数组名   存储datatype 类型的数据int tlen;       // 数组的容量int clen;       // 数组中有效元素的个数
}SeqList;// 顺序表 表头结构SeqList* CreateSeqList(int n);
int InsertTailSeqList(SeqList* sl,DATATYPE*data);
int ShowSeqList(SeqList* sl);
int IsFullSeqList(SeqList* sl);
int GetSizeSeqList(SeqList* sl);
int InsertPosSeqList(SeqList* sl,DATATYPE*data,int pos);
int IsEmptySeqList(SeqList* sl);
int FindSeqListByName(SeqList *ls, char *name);
DATATYPE* GetItemSeqList(SeqList* sl,int pos);
int ClearSeqList(SeqList *sl);
int ModifySeqList(SeqList *sl, char *old, DATATYPE*data);
int DeleteSeqList(SeqList *sl, char *name);
int DestroySeqList(SeqList *sl);
#endif 
-----------------------------------------------------------------
//.c文件
#include "seqlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*** @brief Create a Seq List object  创建一个顺序表** @param n 是顺序表的大小* @return SeqList*  指向顺序表的指针 (重要) ,错误的话返回NULL*/
SeqList *CreateSeqList(int n)
{SeqList *sl = malloc(sizeof(SeqList));if (NULL == sl){fprintf(stderr,"CreateSeqList malloc error\n");  // strerr 专门输出错误信息的return NULL;}sl->head = malloc(sizeof(DATATYPE) * n);if (NULL == sl->head){fprintf(stderr,"CreateSeqList malloc2 error\n");  // strerr 专门输出错误信息的return NULL;}sl->tlen = n;sl->clen = 0;return sl;
}
/*** @brief  顺序表的尾插** @param sl 被插入的 顺序表* @param data 被存储的数据的指针* @return int  0表示成功 1 表示失败*/
int InsertTailSeqList(SeqList *sl, DATATYPE *data)
{if (IsFullSeqList(sl)){return 1;}// strcpymemcpy(&sl->head[sl->clen], data, sizeof(DATATYPE));sl->clen++;return 0;
}
/*** @brief 遍历整个顺序表** @param sl 被遍历的顺序表的指针* @return int 0表示成功 1 表示失败*/
int ShowSeqList(SeqList *sl)
{int size = GetSizeSeqList(sl);int i = 0;for (i = 0; i < size; i++){printf("name:%s sex:%c age:%d score:%d\n", sl->head[i].name,sl->head[i].sex, sl->head[i].age, sl->head[i].score);}return 0;
}int IsFullSeqList(SeqList *sl) { return sl->clen == sl->tlen; }
int GetSizeSeqList(SeqList *sl) { return sl->clen; }int InsertPosSeqList(SeqList *sl, DATATYPE *data, int pos)
{int size = GetSizeSeqList(sl);if (pos < 0 || pos > size){fprintf(stderr,"CreateSeqList malloc2 error\n");  // strerr 专门输出错误信息的return 1;}if (IsFullSeqList(sl)){printf("seqlist full\n");return 1;}int i = 0;for (i = sl->clen; i > pos; i--){memcpy(&sl->head[i], &sl->head[i-1], sizeof(DATATYPE));}memcpy(&sl->head[pos], data, sizeof(DATATYPE));sl->clen++;return 0;
}
int IsEmptySeqList(SeqList* sl)
{return 0 == sl->clen;//逻辑表达式,如果clen=0,返回1
}
/*** @brief 在顺序表中按照名字查找信息* * @param ls * @param name * @return int -1没找到*/
int FindSeqListByName(SeqList *sl, char *name)
{if(IsEmptySeqList(sl))//1执行{return -1;}int size = GetSizeSeqList(sl);int i = 0;for(i=0;i<size;i++){if(0 == strcmp(sl->head[i].name, name)){return i;}}return -1;
}
DATATYPE* GetItemSeqList(SeqList* sl,int pos)
{int size = GetSizeSeqList(sl);if(pos<0 || pos > size-1){return NULL;}return &sl->head[pos];
}
int ClearSeqList(SeqList *sl)
{sl->clen = 0; //本质上就是要新的数据直接覆盖到旧数据的位置上,clen=0意味着旧数据无法写入return 0;
}
int ModifySeqList(SeqList *sl, char *old, DATATYPE*data)
{int ret = FindSeqListByName(sl, old);if(-1 == ret){return  1;}memcpy(&sl->head[ret], data, sizeof(DATATYPE));return 0;
}
int DeleteSeqList(SeqList *sl, char *name)
{int ret = FindSeqListByName(sl, name);if(-1 == ret){return -1;}int i;int size = GetSizeSeqList(sl);for(i=ret;i<size;i++)//循环前移{memcpy(&sl->head[i], &sl->head[i+1], sizeof(DATATYPE));}sl->clen--;return 0;
}
int DestroySeqList(SeqList *sl)
{free(sl->head);free(sl);return 0;
}

五:makefile

1.规范名字 makefile/Makefile //一般用第二个

a.out:main.c seqlist.c//目标:依赖gcc main.c seqlist.c -o a.out//规则clean:rm a.out--------------------------------------------------------
编写完make再make clean
//形式1
#目标:依赖
#\t规则a.out:main.c seqlist.cgcc main.c seqlist.c -o a.out clean:rm a.out 
//形式2
a.out:main.c seqlist.cgcc $^ -o $@//$@   目标:上一条语句// $^	依赖:只在这条规则生效
//形式3
SRC = main.c 
SRC += seqlist.c//在上一套SRC追加'+='
DST = all
$(DST) : $(SRC)gcc $^ -o $@
clean:rm $(DST)
//形式4	适用于大型文件
SRC = main.o 
SRC += seqlist.o
DST = all%.o:%.c		//%代表文件名()通配符,是一个变量,对应的.c文件 生成对应的.o文件gcc -c $^ -o $@
$(DST) : $(SRC)gcc $^ -o $@
clean:rm $(DST)	$(SRC)//也再删.o文件

六:线性表的链式存储

  1. 线性表链式存储结构的特点是一组任意的存储单位存储线性表的数据元素,存储单元可以是连续的,也可以不连续。可以被存储在任意内存未被占用的位置上。

​ 所以前面的顺序表只需要存储数据元素信息就可以了。在链式结构中还需要一个元素存储下一个元素的地址。

​ 为了表示每个数据元素,ai与其直接后继数据元素ai+1之间的逻辑关系,对ai来说,除了存储其本身的信息外,还需要存一个指示器直接后续的信息。把存储元素信息的域叫数据域,把存储直接后继位置的域叫指针域。这两部分信息组成数据元素ai的存储映像,叫结点(Node);

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

typedef struct 
{char name[32];char sex;int age;int score;
}DATATYPE;
------------------------------------------------------------------------------------typedef struct node//必须有名字,不然无法表示引用自己 
{DATATYPE data;struct node *next;
}LinkNode;typedef struct 
{LinkNode *head;int clen;
}LinkList;
int InsertHeadLinkList(LinkList *list, DATATYPE *data)
{//新结点的初始化LinkNode *newnode = malloc(sizeof(LinkNode));if (NULL == newnode){fprintf(stderr, "InsertHeadLinkList malloc\n");return 1;}memcpy(&newnode->data, data, sizeof(DATATYPE));newnode->next = NULL;// 把新节点连接到链表中if (IsEmptyLinkList(list))  // empty{list->head = newnode;}else{newnode->next = list->head;list->head = newnode;}list->clen++;return 0;
}

相关文章:

  • 网络设计培训班百度搜索名字排名优化
  • 网站 百度地图外贸推广方式
  • 南京今天的最新消息windows优化大师会员
  • 做服装最好的网站有哪些北京本地网络推广平台
  • 网站底部版权代码肇庆seo按天计费
  • 做国厂家的网站网站优化查询代码
  • 华为云Flexus+DeepSeek征文 | 基于华为云的 Dify-LLM 企业级 AI 开发平台部署指南
  • AI 产品部署和交付的基础设施——全景解析
  • 【Linux手册】环境变量与命令行参数:贯穿系统与应用的隐形桥梁
  • 09.【C语言学习笔记】指针(一)
  • Spring Ai Alibaba Graph实现五大工作流模式
  • 马克思主义基本原理期末复习下
  • Tomcat服务
  • 60天python训练营打卡day41
  • # Python中等于号的使用
  • 创建首个 Spring Boot 登录项目
  • VSCode源码解析-程序的启动逻辑
  • 彻底拆解 Vue scoped 指令:从编译原理到工程实践的全链路解析
  • 【Spring底层分析】AOP的cligb代理和jdk代理
  • 逆向入门(7)汇编篇-mul指令的学习
  • 《C++》命名空间简述
  • 云电脑,“死”于AI时代前夕 | 数智化观察
  • JVM(12)——详解G1垃圾回收器
  • AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年6月24日第118弹
  • Python移除链表元素-虚拟节点
  • 植物小知识