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

【面试官说实现一个顺序表,但听到要求后我沉默了】

在很多人心里,顺序表是数据结构最基础最简单的东西了,如果面试让我们手撕一道顺序表,相信大家心里早就乐开了花,但是面试官真的会出这么简单的题吗?

 

答案是:当然会,哈哈。

我们来看看面试官的要求:

请实现下面函数的接口,并且自己安排测试用例测试:

void SLInit(SL* ps);//初始化顺序表
void SLPrint(SL* ps);//打印顺序表中有效数据
void SLPushFront(SL* ps, SLDataType x);//头插
void SLPushBack(SL* ps, SLDataType x);//尾插
void SLPopFront(SL* ps);//头删
void SLPopBack(SL* ps);//尾删
int SLFind(SL* ps, SLDataType x);//找到x数据,并返回这是顺序表中第几位,找不到就返回-1
void SLInsert(SL* ps, int pos, SLDataType x);//在表中第pos位后插入数据x
void SLErase(SL* ps, int pos);//删除表中第pos位的数据
void SLDestroy(SL* ps);//释放顺序表

很人多肯定会说,就这就这?? 这不是顺序表的基操吗,有手就行

 但是面试官接着说了一句话:

你能在20分钟内完成吗?你能够保证你的代码鲁棒性很好吗?

大家或许对于20min的概念不是特别强烈,20min实现上面10个函数的接口,并且还要自己测试代码是否有问题,20min内完成,平均每个接口不能超过2min,这还不算测试用例。如果还想让其规范性更高,分成3个文件是避免不了的(   text.c(测试接口功能 )     SeqList.c(接口的定义)   SeqList.h(头文件,接口的声明等等)    ),我自己测试了下,大概用了40多min(我太菜了,各位佬不要喷我)

下面是我实现接口的定义:SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"SeqList.h"

void SLCheckCapacity(SL* ps)
{
	assert(ps);
	int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
	SL* tmp = (SL*)realloc(ps->a, newCapacity * sizeof(SLDataType));
	if (!tmp)
	{
		printf("realloc fail\n");
		exit(-1);
	}
	ps->a = tmp;
	ps->capacity = newCapacity;
}

void SLInit(SL* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

void SLPrint(SL* ps)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d\n", ps->a[i]);
	}
}

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	int end = ps->size;
	while (end > 0)
	{
		ps->a[end] = ps->a[end - 1];
		end--;
	}
	ps->a[end] = x;
	ps->size++;
}

void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	ps->a[ps->size] = x;
	ps->size++;
}

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);
	int begin = 0;
	while (begin < ps->size-1)
	{
		ps->a[begin] = ps->a[begin + 1];
		begin++;
	}
	ps->size--;
}

void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size > 0);
	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 + 1;
		}
	}
	return -1;
}


void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	if (pos > ps->size)
	{
		printf("无法插入\n");
		return;
	}
	SLCheckCapacity(ps);
	int end = ps->size;
	while (end > pos)
	{
		ps->a[end] = ps->a[end - 1];
		end--;
	}
	ps->a[end] = x;
	ps->size++;
}

void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(ps->size > 0);
	int begin = pos;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

void SLDestroy(SL* ps)
{
	assert(ps);
	
	ps->a = NULL;
	ps->capacity = ps->size = 0;
	free(ps);
}

至于测试接口的功能每个人有不同的写法,鄙人的愚见是写一个测一个,出了问题方便及时修改,不然等到一起测试时程序奔溃了那可就要了老命了。另外测试时要尽可能的考虑所有情况,想删除数据时万一表中已经没有了数据应该怎么办?在第几位插入或者删除数据时输入的位置是否有效等等都应该是我们所考虑的。

回到上文,我们要怎样做才能将时间缩短到20min内呢?

这种像我一样硬来的话或许够呛(大佬请自动忽略),那有什么更好的办法吗?

我们发现在第几位删除插入数据好像也能够完成头删尾删头插尾插,举个栗子:

我们想尾插数据,不就是想在最后一位插入数据吗?那我们只要实现了随机插入的接口,头插尾插不也就是间接实现了吗?删除数据也同理。

有了这样的思路后我们不妨来试试写:

void SLInsert(SL* ps, int pos, SLDataType x)
{
	assert(ps);
	if (pos > ps->size)
	{
		printf("无法插入\n");
		return;
	}
	SLCheckCapacity(ps);
	int end = ps->size;
	while (end > pos)
	{
		ps->a[end] = ps->a[end - 1];
		end--;
	}
	ps->a[end] = x;
	ps->size++;
}

void SLErase(SL* ps, int pos)
{
	assert(ps);
	assert(ps->size > 0);
	int begin = pos;
	while (begin < ps->size)
	{
		ps->a[begin - 1] = ps->a[begin];
		begin++;
	}
	ps->size--;
}

void SLPushFront(SL* ps, SLDataType x)
{
	SLInsert(ps, 0, x);
}

void SLPushBack(SL* ps, SLDataType x)
{
	SLInsert(ps, ps->size, x);

}

void SLPopFront(SL* ps)
{
	SLErase(ps, 1);
}

void SLPopBack(SL* ps)
{
	SLErase(ps, ps->size);
}

实现了SLInsert和SLErase这两个接口后实现头插尾插头删尾删就变得容易多了,能够节省很多时间,我又重新测试了一下大概花了20多min(可能是对函数接口不太熟悉的原因,我真的尽力了)

如果大佬有更好的方法,欢迎在评论区提出。

 

相关文章:

  • jquery导航图片全屏滚动、首页全屏轮播图,各式相册
  • 相对于java,C++中的那些神奇语法
  • 元宇宙系列之AI虚拟人:“人”潮汹涌 探路未来
  • Selenium基础 — Selenium操作浏览器窗口滚动条
  • 前端经典面试题 | 闭包的作用和原理
  • python+opencv实现人脸微整形
  • 分类-朴素贝叶斯(高斯、多项式、伯努利)
  • Windows10搭建ASP服务器
  • IPv中的地域分布
  • 基于ssm红联小区果蔬销售网站的设计与实现-计算机毕业设计源码+LW文档
  • Python实现视频自动打码,不用担心透露隐私了
  • 【目标检测】【边界框回归】Bounding-Box regression
  • hive与impala相关
  • C#语言里对TCP接收数据的分包处理
  • 我的Mysql突然挂了(Communications link failure)
  • 【译】JS基础算法脚本:字符串结尾
  • 「译」Node.js Streams 基础
  • 【前端学习】-粗谈选择器
  • Bootstrap JS插件Alert源码分析
  • Effective Java 笔记(一)
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • iOS 系统授权开发
  • js操作时间(持续更新)
  • Redis学习笔记 - pipline(流水线、管道)
  • Vue2.0 实现互斥
  • 第2章 网络文档
  • 模型微调
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 如何用Ubuntu和Xen来设置Kubernetes?
  • 什么是Javascript函数节流?
  • 微信端页面使用-webkit-box和绝对定位时,元素上移的问题
  • 携程小程序初体验
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 再次简单明了总结flex布局,一看就懂...
  • 【云吞铺子】性能抖动剖析(二)
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • ######## golang各章节终篇索引 ########
  • #1015 : KMP算法
  • $NOIp2018$劝退记
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (附源码)ssm码农论坛 毕业设计 231126
  • (含笔试题)深度解析数据在内存中的存储
  • (离散数学)逻辑连接词
  • (五)Python 垃圾回收机制
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • (杂交版)植物大战僵尸
  • .NET Core 通过 Ef Core 操作 Mysql
  • .NET 服务 ServiceController
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .Net接口调试与案例
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • [ C++ ] STL---仿函数与priority_queue
  • [ SNOI 2013 ] Quare