草庐IT

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

Fox! 2023-05-05 原文

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

答案是:当然会,哈哈。

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

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

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;
	SLDataType* tmp = (SLDataType*)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(可能是对函数接口不太熟悉的原因,我真的尽力了)

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

有关【面试官说实现一个顺序表,但听到要求后我沉默了】的更多相关文章

  1. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  2. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  3. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  4. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  5. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  6. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  7. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  8. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  9. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  10. ruby - 一个 YAML 对象可以引用另一个吗? - 2

    我想让一个yaml对象引用另一个,如下所示:intro:"Hello,dearuser."registration:$introThanksforregistering!new_message:$introYouhaveanewmessage!上面的语法只是它如何工作的一个例子(这也是它在thiscpanmodule中的工作方式。)我正在使用标准的ruby​​yaml解析器。这可能吗? 最佳答案 一些yaml对象确实引用了其他对象:irb>require'yaml'#=>trueirb>str="hello"#=>"hello"ir

随机推荐