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

《数据结构笔记二》:顺序表

线性表

线性表的定义与特点

由n(n>=0)个数据特性相同的元素构成的有限序列,称为线性表

线性表是n个数据元素的有限序列,其中n个数据的是相同的数据类型

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

对于非空的线性表或线性结构,其特点是:

存在唯一的一个被称之为 “第一个” 的数据元素

存在唯一的一个被称之为 “最后一个” 的数据元素

除第一个元素外,结构中的每一个数据元素均只有一个前驱

除最后一个元素外,结构中的每一个数据元素均只有一个后继

简单举例:

#include<stdio.h>#include<string.h>struct book{int              ISBN;              //书号char         bookname;       //书名double      price;              //定价}int main(int argc ; char const *argv){book B; //定义一个书的变量B.ISBN = 9527; //书号strcpy = (B.bookname,"c语言程序设计");//书名B.price = 666; //定价return 0;}

顺序表

用一组连续的内存单元依次存储线性表的各个元素,也就是说,逻辑上相邻的元素,实际的物理存储空间也是连续的

顺序表---存储结构

#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAXSIZE = 100;tydepef int     ELemType;//顺序表定义操作tydepef struct{ELemType data[MAXSIZE];int length;}SeqList;//顺序表初始化操作void initList (SeqList *L){L -> length = 0;}//在尾部添加元素操作int appendElem(SeqList *L , ElemType a){if(L->length >= MAXSIZE){printf("顺序表已满,无法添加\n");return 0;}else{L->data[L->length] = a; //否则顺序表未满,可以添加L->lenght++; //更新 length 的值}return 1; //成功返回 1 失败返回 0        }//遍历操作void listElem(SeqList *L){for(int i = 0; i < L->length ; i++){printf("%d\n", L -> data[ i ]);    }printf("\n");}//插入数据元素操作int insertElem(SeqList *L , int position , ElemType a){if(    L->length >= MAXSIZE    ){printf(  "顺序表已满,无法插入数据\n"  );return 0;}if( position >1 || position > L->length   ){printf(    "插入位置错误\n"    );return 0 ;}if(position <= L->length){for(int i = L->length-1 ; i >= position-1 ; i--){L->data[i+1] = L->length[ i ];}L->data[position - 1] = a;L->length++ //更新 length 的值}return 1;}//删除数据元素操作int deleteElem(Seqlist *L , int position , ElemType *e){*e = L->data[position - 1]; //赋值要删除的值if(position < L->length){for(int i = position; i < L->length ; i++) //从要删除的位置一直往后循环,一直循环到最大的那个元素{L->data[i - 1] = L->data[ i ];}}L->length--;return 1;    }//查找数据位置操作int findElem(SeqList *L , ElemType a ) //传了一个表 ,传了一个元素, 然后找到这个元素位置{if(L -> length = 0) //先来一个判断是否表为空?{printf("空列表\n");return 0 ;}for(int i = 0 ; i < L -> length ; i++) //然后循环对比 挨个对比{if(L -> data[ i ] == a)         //一旦找到这个元素{return i + 1; //返回一个 i +1 , 就是它在这个顺序表中的位置}}return 0 ;}int main(int argc ; char const *argv){//声明一个顺序表并初始化SeqList list;initList(&list);printf("初始化成功,目前长度占用%d\n",list.length);printf(“目前占用内存%zu字节\n”,sizeof(list.data));appendElem(&list,88);       appendElem(&list,77);appendElem(&list,66);appendElem(&list,55); listElem( &list );     //遍历了一下insertElem(&list , 2 ,44); //在第二个位置插入了一个44listElem( &list );    //遍历了一下ElemType delData;deleteElem(&list , 2, &delData);printf("被删除的数据元素为: %d \n", &delData);listElem( &list );    //重新遍历了一下printf("查找的这个元素的位置为:%d\n" , findElem(&list , 88))return 0;}

输出结果:

初始化成功,目前长度占用0

目前占用内存400字节

88 77 66 55

88 44 77 66 55

被删除的数据元素为:44

88 77 66 55

查找的这个元素的位置为:1

思考:顺序表插入数据的最好和最坏的时间复杂度

答:O(1) O(n)

在顺序表中,进行动态分配内存地址初始化

例子

#include <stdio.h> 
#include <stdlib.h>typedef struct 
{ int *data; int size; int capacity; 
} SeqList;// 初始化顺序表 
void SeqListInit(SeqList *list, int initialCapacity)
{ list->data = (int *)malloc(initialCapacity * sizeof(int));if (list->data == NULL) { fprintf(stderr, "内存分配失败!\n"); exit(EXIT_FAILURE); } list->size = 0;list->capacity = initialCapacity; 
}// 销毁顺序表 
void SeqListDestroy(SeqList *list)
{ free(list->data); list->data = NULL;list->size = 0;list->capacity = 0;
}// 示例:插入元素(简单扩容) 
void SeqListPushBack(SeqList *list, int value)
{ if (list->size >= list->capacity) { // 容量不足时,扩容为原来的2倍int newCapacity = list->capacity * 2; int *newData = (int *)realloc(list->data, newCapacity * sizeof(int));if (newData == NULL){ fprintf(stderr, "扩容失败!\n");exit(EXIT_FAILURE); } list->data = newData;list->capacity = newCapacity; } list->data[list->size++] = value; 
}int main(int argc , char  const *argv) 
{ SeqList list; SeqListInit(&list, 4); // 初始容量设为4// 插入元素测试 SeqListPushBack(&list, 10); SeqListPushBack(&list, 20); printf("当前元素个数: %d, 容量: %d\n", list.size, list.capacity);SeqListDestroy(&list); // 释放内存 return 0;
}

运行结果

当前元素个数: 2, 容量: 4

关键点解释

  1. 动态内存分配:使用 malloc 在堆上分配内存,避免栈溢出。

  2. 错误处理:检查 malloc 或 realloc 是否返回 NULL,防止内存分配失败导致程序崩溃。

  3. 扩容机制:当插入元素发现空间不足时,通过 realloc 重新分配更大的内存(通常按2倍扩容以减少频繁扩容)。

  4. 资源释放:使用 free 释放内存,并将指针置为 NULL,避免野指针问题。

http://www.xdnf.cn/news/8174.html

相关文章:

  • 【技术追踪】ADDP:通过交替去噪扩散过程学习用于图像识别和生成的通用表示(ICLR-2024)
  • Java中static关键字深度解析:从入门到高阶实战
  • 碰一碰发视频源码搭建定制化开发详解,支持OEM
  • One-shot和Zero-shot的区别以及使用场景
  • 嵌入式STM32学习——串口USART 2.3(串口发送数据控制LED灯)
  • 一文读懂GRPC
  • Django的请求和响应+template模板
  • CentOS7/Ubuntu SSH配置允许ROOT密码登录
  • LeRobot的机器人控制系统(上)
  • 无人机避障——深蓝学院浙大栅格地图以及ESDF地图内容
  • BlazeMeter录制jmeter脚本
  • 2025年系统架构师---综合知识卷
  • FreeBSD14.2因为爆内存而导致Xfce4视窗被卡,桌面变黑色,只能看到鼠标在窗体中心,鼠标无反应,键盘无反应
  • 03_基础篇-NumPy(下):深度学习中的常用操作
  • deepseek调用
  • QT ui控件setEnabled(false) 作用
  • SpringBoot系列之OpenAI API 创建智能博客评论助手
  • 人工智能培训:解锁未来职场竞争力的核心路径与课程内容解析
  • 【JAVA基础】什么情况下可以直接使用类名.方法名调用方法?
  • 【VLNs篇】05:TGS-在无地图室外环境中使用视觉语言模型进行轨迹生成和选择
  • python实现web请求与响应
  • Java中创建线程的几种方式
  • 【C++/控制台】简易五子棋游戏
  • LeetCode 257. 二叉树所有路径求解:回溯算法的深度解析与实践
  • 力扣热题——罗马数字转整数
  • 降低诊断消息转发延迟与缓冲区内存占用优化方案
  • Ubuntu 通过指令远程命令行配置WiFi连接
  • StickyNotes,简单便签超实用
  • Oracle 数据文件被删除后使用rman备份恢复过程
  • AI大模型应用之评测篇