[数据结构初阶]顺序表
创始人
2024-04-02 06:33:01
0

目录

线性表

顺序表

 1. 静态顺序表:使用定长数组存储元素。

2. 动态顺序表:使用动态开辟的数组存储。

接口实现 

SeqList.h

SeqList.c

 Test.c

 数组相关面试题

 顺序表的问题及思考


线性表

        线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...         线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

顺序表

        顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。         顺序表相较于链表有一个要求,数据必须从第一个位置连续存储的!         顺序表一般可以分为:

 1. 静态顺序表:使用定长数组存储元素

#pragma once
#define N 100
typedef int SLDataType;
struct SeqList
{SLDataType a[N];int size;
};

2. 动态顺序表:使用动态开辟的数组存储。

#pragma once
typedef int SLDataType;
struct SeqList
{SLDataType* a;int size;int capacity;//容量
};

接口实现 

SeqList.h

#pragma once
typedef int SLDataType;
typedef struct SeqList
{SLDataType* a;int size;int capacity;//容量
}SL;
void SLInit(SL* ps);void SLDestory(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);
void SLModify(SL* ps, int pos,int x);void SLPrint(SL* ps);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
#include
#include
#includevoid SLInit(SL* ps) {assert(ps != NULL);ps->a = NULL;ps->size = ps->capacity = 0;
}void SLCheckCapacity(SL* ps)
{assert(ps != NULL);if (ps->capacity == ps->size){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL) {printf("realloc fall\n");exit(-1);}ps->a = tmp;ps->capacity = newcapacity;}
}void SLPushBack(SL* ps, SLDataType x) {assert(ps != NULL);/*SLCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;*/SLInsert(ps, ps->size, x);
}void SLPrint(SL* ps) {assert(ps != NULL);for (int i = 0; i < ps->size; ++i){printf("%d", ps->a[i]);}printf("\n");}void SLDestory(SL* ps)
{assert(ps != NULL);if (ps -> a){free(ps->a);ps->a = NULL;ps->capacity = 0;ps->size = 0;}
}void SLPushFront(SL* ps, SLDataType x) {/*assert(ps != NULL);SLCheckCapacity(ps);int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;*/SLInsert(ps, 0, x);
}void SLpopBack(SL* ps) {assert(ps != NULL);/*if (ps->size == 0){printf("SeqList is empty");return;}*/assert(ps->size > 0);ps->size--;
}void SLpopFront(SL* ps) {assert(ps != NULL);assert(ps->size > 0);/*int begin = 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];++begin;}ps->size--;*/SLErase(ps, 0);
}void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps != NULL);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;}void SLErase(SL* ps, int pos) {assert(ps != NULL);assert(pos >= 0 && pos < ps->size);int begin = pos;while (begin < ps-> size - 1){ps->a[begin] = ps->a[begin + 1];++begin;}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;
}void SLModify(SL* ps, int pos,int x)
{assert(ps);assert(pos >= 0 && pos < ps->size);ps->a[pos] = x;
}

 Test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
#include
#include
void menu()
{printf("*****************************************************************\n");printf("1、查找      2、修改\n");printf("3、尾插      4、头插\n");printf("5、任意删    6、任意插\n");printf("7、尾删      8、头删\n");printf("9、打印     -1、退出\n");printf("*****************************************************************\n");}int main()
{SL s1;SLInit(&s1);int option ;do {menu();if (scanf("%d", &option) == EOF){printf("scanf输入错误\n");break;}int val, pos;switch (option){case -1:printf("退出\n");exit(0);break;case 1:printf("请输入你要查找的值\n");int x;scanf("%d", &x);int pos = SLFind(&s1, x);printf("在%d位置处\n",pos);break;case 2: {int y;int z;printf("请输入你要修改的值和修改后的值\n");scanf("%d%d", &y, &z);pos = SLFind(&s1, y);if (pos != -1){SLModify(&s1, pos, z);}else{printf("没找到:%d\n", y);}break;}case 3:printf("请连续输入你要尾插的数据,以0结束:\n");scanf("%d", &val);while (val!=0){SLPushBack(&s1, val);scanf("%d", &val);}break;case 4:printf("请连续输入你要头插的数据,以0结束:\n");scanf("%d", &val);while (val != 0){SLPushFront(&s1, val);scanf("%d", &val);}break;case 5:{int y;printf("请输入你要删除的位置\n");scanf("%d", &y);SLErase(&s1, y);break;}case 6:{int y;int x;printf("请输入你要插入的位置,和插入的值\n");scanf("%d%d", &y, &x);SLInsert(&s1, y, x);break;}case 7:SLpopBack(&s1);break;case 8:SLpopFront(&s1);break;case 9:SLPrint(&s1);break;default:exit(-1);break;}} while (option != -1);SLDestory(&s1);return 0;
}

 

 数组相关面试题

1、分析以下函数的空间复杂度(   )

        A.O(n)

        B.O(n^2)

        C.O( 1 )

        D.O(nlogn)

int** fun(int n) {int ** s = (int **)malloc(n * sizeof(int *));while(n--)s[n] = (int *)malloc(n * sizeof(int));return s;}

  答案解析:

此处开辟的是一个二维数组,数组有n行,每行分别有1,2,3,...n列,所以是n(n + 1)/2个元素空间,空间复杂度为n^2

2、如果一个函数的内部中只定义了一个二维数组a[3][6],请问这个函数的空间复杂度为(   )

        A.O(n)

        B.O(n^2)

        C.O( 1 )

        D.O(m*n)

 答案解析:

函数内部数组的大小是固定的,不论函数运行多少次,所需空间都是固定大小的,因此空间复杂度为O(1)

27. 移除元素 - 力扣(LeetCode)


int removeElement(int* nums, int numsSize, int val){int src = 0, dst = 0;while(src < numsSize){if(nums[src] == val){src++;}else{nums[dst++] = nums[src++];}}return dst;}
​
int removeElement(int* nums, int numsSize, int val){int j = 0;int i = 0;for(i = 0;i < numsSize; ++i){if(nums[i] == val){for(j = i+1;j < numsSize;j++){   nums[j-1] = nums[j];}numsSize--;i--;}}return numsSize;
}​

26. 删除有序数组中的重复项 - 力扣(LeetCode)

int removeDuplicates(int* nums, int numsSize){int left = 0;int right = 0;while(right

88. 合并两个有序数组 - 力扣(LeetCode)

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){int num1right = m - 1;int num2right = n - 1;int a = m + n - 1;while(num1right >= 0 || num2right >= 0){if(num2right < 0){nums1[a--] = nums1[num1right--];}else if(num1right < 0){nums1[a--] = nums2[num2right--];}else if(nums1[num1right] >= nums2[num2right]){nums1[a--] = nums1[num1right--];}else{nums1[a--] = nums2[num2right--];}} 
}

 顺序表的问题及思考

1. 中间/头部的插入删除,时间复杂度为O(N) 2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。 3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。 思考:如何解决以上问题呢?去下篇博客看看链表。

相关内容

热门资讯

银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...