【数据结构c实现】顺序表实现

文章目录

  • 线性表
    • 线性表的顺序实现
      • 顺序表结构
      • 顺序表初始化
      • 增配空间Inc
      • 打印顺序表show_list
      • 线性表长度length
      • 尾部插入push_back
      • 头部插入push_front
      • 尾部删除pop_back
      • 头部删除pop_front
      • 按位置插入insert_pos
      • 按值查找find
      • 按位置删除delete_pos
      • 按值删除delete_val
      • 排序sort(冒泡;升序)
      • 逆置resver
      • 清除表clear
      • 销毁表destroy
      • 合并表merge

线性表

在数据元素的非空有限集中,(1)存在唯一的一个被称做“第一个”的数据元素;(2)存在唯一的一个被称做“最后一个”的数据元素;(3)除第一个之外,集合中的每个数据元素均只有一个前驱;(4)除最后一个之外,集合中每个数据元素均只有一个后继

线性表的顺序实现

线性表的顺序表示指的是用一组地址连续的存储单元依次存储线性表的数据元素。

顺序表结构

#define SEQLIST_INIT_SIZE 8typedef struct SeqList {ElemType *base; // 线性表首地址int capacity; // 开辟的内存空间int size; // 有效存储
} SeqList;

在这里插入图片描述

顺序表初始化

开辟出一段空间(给定空间大小)

void InitSeqList(SeqList *list) {list->base = (ElemType *) malloc(sizeof(ElemType) * SEQLIST_INIT_SIZE);//开辟空间assert(list->base != NULL);list->capacity = SEQLIST_INIT_SIZE;list->size = 0;
}

malloc动态内存分配函数,用于申请一块连续的指定大小的内存块区域以ElementType *类型返回分配的内存区域地址:格式:指针名=(指针类型*)malloc(sizeof(指针类型)*数据数量)

②如果表达式的结果为“假”,assert()会打印出断言失败的信息Assertion failed:...,并调用abort()函数终止程序的执行Process finished with exit code 3;如果表达式的结果为“真”,assert()就什么也不做,程序继续往后执行

增配空间Inc

1.重新开辟内存空间,并判断是否增配空间成功,失败则增配失败返回false

2.更新结点线性表首地址和开辟的内存空间

3.之后每次插入数据操作前,添加判断条件:分配给表内存是否足够。不够则进行增配空间,增配空间失败时,才是真正的内存不足

#define INC_SIZE 3bool Inc(SeqList *list) {//对已有的空间进行分配,原来表开辟内存8,进行重新分配,即开辟8+3内存ElemType *newbase = (ElemType *) realloc(list->base, sizeof(ElemType) * (list->capacity + INC_SIZE));if (newbase == NULL) {printf("增配空间失败,内存不足\n");return false;}list->base = newbase;list->capacity += INC_SIZE;return true;
}

realloc函数指向在堆区重新开辟的内存块的起始地址:realloc(先前开辟的内存块的指针--也就是malloc之前申请的那块内存空间,即需要调整大小的内存空间,新开辟的那块内存空间的字节数),返回值为调整之后的内存的起始地址

打印顺序表show_list

void show_list(SeqList *list) {for (int i = 0; i < list->size; i++) {printf("%d", list->base[i]);}printf("\n");
}

线性表长度length

int length(SeqList *list) {return list->size;
}

尾部插入push_back

插入6 7 9后顺序表中数据顺序为:6 7 9

1.判断有效存储是否小于开辟的内存空间,即判断开辟的空间是否已满,满了不能插入数据

2.通过下标赋值,即插入数据

3.更新顺序表有效存储长度

void push_back(SeqList *list, ElemType x) {if (list->size >= list->capacity && !Inc(list)) {printf("顺序表空间已满,%d不能尾部插入数据\n", x);return;}list->base[list->size] = x;list->size++;
}

头部插入push_front

插入6 9 1后顺序表中数据顺序为:1 9 6

1.判断有效存储是否小于开辟的内存空间,即判断开辟的空间是否已满,满了不能插入数据

2.size-1即表中最后一个数据的下标,从最后一个数据开始依次向后移动

3.赋值到下标为0的地址,即插入数据

4.更新顺序表有效存储长度

void push_front(SeqList *list, ElemType x) {if (list->size >= list->capacity && !Inc(list)) {printf("顺序表空间已满,%d不能头部插入数据\n", x);return;}for (int i = list->size; i > 0; i--) {list->base[i] = list->base[i - 1];}list->base[0] = x;list->size++;
}

尾部删除pop_back

有顺序表1 6 9进行尾部删除后:1 6

1.判断size是否为0,即表是否为空,空表不能删除数据

2.有效长度减1

void pop_back(SeqList *list) {if (list->size == 0) {printf("顺序表空间已空,不能尾部删除数据\n");return;}list->size--;
}

头部删除pop_front

有顺序表5 6 0进行头部删除后:6 0

1.判断size是否为0,即表是否为空,空表不能删除数据

2.从第二个数据开始,依次往前移动

3.有效长度减1

void pop_front(SeqList *list) {if (list->size == 0) {printf("顺序表空间已空,不能头部删除数据\n");return;}for (int i = 0; i < list->size - 1; i++) {list->base[i] = list->base[i + 1];}list->size--;
}

按位置插入insert_pos

在顺序表5 3 0下标为2的位置插入数据7为:5 3 7 0

1.判断pos是否正确并小于有效存储长度,即判断插入位置是否合法,位置非法不能插入数据

2.判断有效存储是否小于开辟的内存空间,即判断开辟的空间是否已满,满了不能插入数据

3.从最后一个数据开始依次向后移动,直到要插入数据的位置移动结束

4.通过下标赋值,即插入数据

5.更新顺序表有效存储长度

void insert_pos(SeqList *list, int pos, ElemType x) {if (pos < 0 || pos > list->size) {printf("插入数据的位置非法,不能插入数据\n");}if (list->size >= list->capacity && !Inc(list)) {printf("顺序表空间已满,%d不能按位置插入数据\n", x);return;}for (int i = list->size; i > pos; i--) {list->base[i] = list->base[i - 1];}list->base[pos] = x;list->size++;
}

特殊情况:当要插入数据的位置==有效存储长度时,即尾部插入时,不影响效率[特别注意]

按值查找find

(第一个符合条件的)

1.从顺序表第一个数据开始向后遍历

2.每次遍历判断该数据是否是要查找的数据,查找成功返回当前下标

3.遍历结束,即没查到数据,返回-1

int find(SeqList *list, ElemType key) {for (int i = 0; i < list->size; i++) {if (list->base[i] == key)return i;}return -1;
}

按位置删除delete_pos

顺序表5 3 0删除位置为1的数据后:5 0

1.判断pos是否正确并小于有效存储长度,即判断删除位置是否合法,位置非法不能删除数据

2.从要删除的位置开始,依次将后一个数据前移

3.更新顺序表有效存储长度

void delete_pos(SeqList *list, int pos) {if (pos < 0 || pos >= list->size)printf("删除数据的位置非法,不能删除数据\n");for (int i = pos; i < list->size - 1; i++) {list->base[i] = list->base[i + 1];}list->size--;
}

按值删除delete_val

顺序表5 3 0删除值为0的数据后:5 3

1.判断要删除的数据是否存在,即按值查找,存在得到查找到的数据下标,不存在得到-1

2.判断返回值是否是-1,是则数据不存在无法删除,否则按位置删除

void delete_val(SeqList *list, ElemType key) {int pos = find(list, key);if (pos == -1) {printf("要删除的数据不存在\n");return;}delete_pos(list, pos);
}

排序sort(冒泡;升序)

顺序表5 3 0 1 9 4排序后:0 1 3 4 5 9

1.两层遍历,依次比较两个数据,前面数据大于后面数据则交换

void sort(SeqList *list) {for (int i = 0; i < list->size; i++) {for (int j = 0; j < list->size - i - 1; j++) {if (list->base[j] > list->base[j + 1]) {ElemType tmp = list->base[j];list->base[j] = list->base[j + 1];list->base[j + 1] = tmp;}}}
}

逆置resver

顺序表5 3 0 1 9 4逆置后:4 9 1 0 3 5

1.判断顺序表长度是否可进行逆置操作操作,长度为1或0时不需要

2.设置两个整型指针low和high,分别指向第一个数据和最后一个数据,low指针后移,high指针前移,每次将两个指针指向的数据对换,直到low指针大于或等于high指针为止

void resver(SeqList *list) {if (list->size == 0 || list->size == 1)return;int low = 0;int high = list->size - 1;ElemType tmp;while (low < high) {tmp = list->base[low];list->base[low] = list->base[high];list->base[high] = tmp;low++;high--;}
}

清除表clear

void clear(SeqList *list) {list->size = 0;
}

销毁表destroy

void destroy(SeqList *list) {free(list->base);list->base = NULL;list->capacity = 0;list->size = 0;
}

free函数必须和malloc函数同时使用

free只能释放由malloc动态分配在堆内存的内存,直接在主函数定义结构体变量是分配在栈内存里的内存,所以释放不了

合并表merge

表A1 2 5 6,表B3 4 7 9,合并后:1 2 3 4 5 6 9

1.设置iaibic三个整型指针,分别用来遍历表A、B、合并表,开辟存放合并表的内存空间,并判断是否开辟成功

2.同时遍历表A和表B,依次判断指针指向的A、B表的数据大小,将较小的数据放入合并表,每存入一个数据,合并表和被存入的数据所在表的整型指针都向后移一次,直到A、B有一个表遍历完

3.如果其中一个表遍历结束,另一个表还有遍历完的数据,则直接将剩余数据依次存入合并表

4.更新合并表有效存储长度

void merge(SeqList *lt, SeqList *la, SeqList *lb) {lt->capacity = la->size + la->size;lt->base = (ElemType *) malloc(sizeof(ElemType)*lt->capacity);assert(lt->base != NULL);int ia = 0;int ib = 0;int ic = 0;while(ia<la->size && ib<lb->size){if(la->base[ia] < lb->base[ib])lt->base[ic++] = la->base[ia++];elselt->base[ic++] = lb->base[ib++];}while(ia < la->size){lt->base[ic++] = la->base[ia++];}while(ib < lb->size){lt->base[ic++] = lb->base[ib++];}lt->size = la->size + lb->size;
}

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

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

相关文章

VSCode解决本地浏览器需要跨域问题

这里写目录标题 测试用代码执行代码后控制台报错现象解决方案 测试用代码 先把测试用的代码贴出来 测试代码结构 index.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Com…

ShellCode注入程序

程序功能是利用NtQueueApcThreadEx注入ShellCode到一个进程中&#xff0c;程序运行后会让你选择模式&#xff0c;按1为普通模式&#xff0c;所需的常规API接口都是使用Windows原本正常的API&#xff1b;在有游戏保护的进程中Windows原本正常的API无法使用&#xff0c;这时候需要…

Android自定义图片涂鸦View实现绘制和橡皮擦功能

在Android应用开发中,涂鸦功能是一个常见的需求,用户可以在画布上进行自由绘制和擦除操作。本文将介绍如何使用自定义View来实现一个具备绘制和橡皮擦功能的涂鸦View,并提供了相关示例代码。 1. 引言 在移动应用开发中,涂鸦功能为用户提供了一种直观的绘图体验,并广泛应用…

怎么制作GIF动图?教你这几个简单方法

怎么制作gif动图&#xff1f;GIF动图是一种非常有趣且实用的图片格式&#xff0c;它能够以短小精悍的方式展示动画效果&#xff0c;因此在社交媒体和聊天应用中备受追捧。本文将向您介绍几种制作GIF动图的方法&#xff0c;让您轻松制作出自己的动图。 GIF动图制作方法一&#x…

音视频技术开发周刊 | 323

每周一期&#xff0c;纵览音视频技术领域的干货。 新闻投稿&#xff1a;contributelivevideostack.com。 Meta牵头组建开源「AI复仇者联盟」&#xff0c;AMD等盟友800亿美元力战OpenAI英伟达 超过50家科技大厂名校和机构&#xff0c;共同成立了全新的人工智能联盟。以开源为旗号…

建立海外SD-WAN专线网络的成本分析

高速、稳定的网络连接是企业成功拓宽海外市场和开展海外业务的关键因素之一。作为一种提供更高质量和性能的连接的网络解决方案&#xff0c;海外SD-WAN专线被越来越多的企业选择。以下将详细介绍建立海外SD-WAN专线网络的成本组成&#xff0c;以协助企业更全面地了解和规划对网…

C#基础——类、对象和属性

C# 属于 面向对象 的编程&#xff0c;“万物皆对象” 面向对象编程的三大特性&#xff1a;封装、继承、多态。 通过类能过较好的体现该语言的特点 类&#xff1a;是具有相同属性和行为特征的集合 类的语法格式&#xff1a; 访问修饰符 class关键字 类名 两种创建类的方式 第…

单片机Freertos入门(二)任务的创建、删除

1、串口配置 首先将串口进行配置&#xff0c;后续经常会应用&#xff0c;具体步骤点击&#xff1a;串口配置。 2、任务 创建一个任务&#xff0c;就是开辟一个空间、每个任务中都会有while&#xff08;1&#xff09;死循环。 2.1相关函数 动态创建&#xff1a;xTaskCreate…

Attention机制学习

写在前面 注意力机制是一个很不错的科研创新点方向&#xff0c;但是没有系统记录过学习过程&#xff0c;这里记录科研中遇到的各种注意力机制。 1. Attention机制解释 本质上来说用到attention的任务都有Query&#xff0c;Key&#xff0c;Value三个关键components&#xff0c;…

Tekton 基于 gitlab 触发流水线

Tekton 基于 gitlab 触发流水线 Tekton EventListener 在8080端口监听事件&#xff0c;Gitlab 提交代码产生push 事件&#xff0c;gitlab webhook触发tekton流水线执行。 前置要求&#xff1a; kubernetes集群中已部署 tekton pipeline、tekton triggers以及tekton dashboa…

c YUV 转 JPEG(准备霍夫曼编码)

先取yuv 文件中一个168的块&#xff0c;跑通全流程 理解与思路&#xff1a; 1.块分割 YUV 文件分为&#xff1a;YUV444 YUV 422 YUV420。444:就是&#xff1a;12个char 有4个Y&#xff0c;4个U&#xff0c;4个 U&#xff0c;422&#xff1a;8个char 中有4个Y &#x…

Python (九)requests

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…