面试题杂货铺 ( 一)

1、 以下程序的功能是()

#include<stdio.h>
int main(void)
{
    FILE *fp;
    long int n;
    fp = fopen("wj.txt","rb");
    fseek(fp , 0 , SEEK_END);
    n = ftell(fp);
    fclose(fp);
    printf("%ld",n);
}

2、实现字符串反转函数

/* 微软crt版本,详见 ..\VC\crt\src\strrev.c */
char *strrev(char *string)
{
    char *start = string;
    char *left = string;
    char ch;

    while (*string++)
            ;
    string -= 2;

    while (left < string)
    {
        ch = *left;
        *left++ = *string;
        *string-- = ch;
    }

    return start;
}

3、数据库事物的属性

数据库事务的属性-ACID(四个英文单词的首写字母):

1)原子性(Atomicity)

所谓原子性就是将一组操作作为一个操作单元,是原子操作,即要么全部执行,要么全部不执行。

2)一致性(Consistency)

事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。如果事务成功地完成,那么系统中所有变化将正确地应用,系统处于有效状态。如果在事务中出现错误,那么系统中的所有变化将自动地回滚,系统返回到原始状态。

3)隔离性(Isolation)

隔离性指并发的事务是相互隔离的。即一个事务内部的操作及正在操作的数据必须封锁起来,不被其它企图进行修改的事务看到。

4)持久性(Durability)

持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。即一旦一个事务提交,DBMS(Database Management System)保证它对数据库中数据的改变应该是永久性的,持久性通过数据库备份和恢复来保证。


4、进程之间的通信方式有哪几种

(1)管道(pipe)及有名管道(named pipe):管道可用于具有亲缘关系的父子进程间的通信,有名管道除了具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
(2)信号(signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一致的。
(3)消息队列(message queue):消息队列是消息的链接表,它克服了上两种通信方式中信号量有限的缺点,具有写权限得进程可以按照一定得规则向消息队列中添加新信息;对消息队列有读权限得进程则可以从消息队列中读取信息。
(4)共享内存(shared memory):可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据得更新。这种方式需要依靠某种同步操作,如互斥锁和信号量等。
(5)信号量(semaphore):主要作为进程之间及同一种进程的不同线程之间得同步和互斥手段。
(6)套接字(socket):这是一种更为一般得进程间通信机制,它可用于网络中不同机器之间的进程间通信,应用非常广泛。


5、数据存储在磁盘上的排列方式会影响I/O服务的性能,一个圆环的磁道上有10个物理块,10个数据记录R1——R10存放在这个磁道上,记录的安排顺序如下表所示:

物理块12345678910
逻辑记录R1R2R3R4R5R6R7R8R9R10

  假设磁盘的旋转速度为20ms/周,磁盘当前处在R1的开头处,若系统顺序扫描后将数据放入单缓冲区内,处理数据的时间为4ms(然后再读取下个记录),则处理这10个记录的最长时间为多少?

答:204ms

因为磁盘的旋转速度为20ms/周,且该磁盘上有10个物理块分别存放着R1—–R10这10个数据记录,所以读取一条记录的速率为: 20/10 = 2(ms/记录)。

R1的处理:由于磁盘开始处在R1的开头处,所以直接读取R1(2ms),处理R1的数据花费时间为(4ms),总共耗时2ms + 4ms = 6ms。
R2的处理:完成R1时磁盘已经移动了6(ms)/2(ms/记录) = 3个记录,磁盘目前处在R4的开头,题目要求顺序处理记录,所以,须要等磁头移动到R2时才能进行读取和数据处理,等待的时间为磁盘扫描过R4、R5、….R10、R1共8个记录的时间(8*2 = 16ms),此时磁盘处在R2的开头,再读取和处理R2花费(2ms(读取)+4ms(处理) = 6ms),所以总共花费16 + 6 = 22ms。
R3—-R10的分析与R2的类似:每个记录的处理时间均为22ms。
总共的处理时间R1 + R2….R10 = 6 + 9 * 22 = 204ms.


<think>好的,我现在需要帮用户整理关于单链表操作实现的心得体会,包括算分析、改进方和经验教训。首先,我得回忆一下单链表的基本操作,比如入、删除查找等,以及它们的实现步骤。 用户提到了算分析,我需要分析这些操作的时间复杂度。比如,入和删除在已知节点的情况下是$O(1)$,但如果需要先查找,那就是$O(n)$。这点很重要,要明确区分不同情况下的性能差异。 接下来是改进设想。用户可能希望优化单链表的某些操作。比如,可以添加尾指针来提升尾部入的效率,这样就不用每次都遍历整个链表。另外,使用双向链表或者循环链表也是常见的改进方,但用户问的是单链表,可能需要说明这些扩展结构的不同应用场景。 经验教训部分,用户可能遇到了指针操作的问题,比如内存泄漏或者野指针。这时候需要强调正确管理指针的重要性,以及如何通过工具或测试来避免这些问题。比如,使用Valgrind检测内存泄漏,或者编写测试用例覆盖边界情况。 然后,我需要参考用户提供的引用内容。引用[1]提到链表操作和存储结构,这和用户的问题直接相关,应该引用到心得中。引用[3]涉及计算机系统知识,可能可以联系到内存管理或程序优化方面,但需要自然衔接,不能强行入。 生成相关问题的时候,要考虑用户可能进一步想知道的内容,比如单链表和双向链表的比较,或者如何测试链表代码的有效性。这些问题应该与用户的问题相关,并且帮助深化他们的理解。 最后,要确保整个回答结构清晰,分点列出,使用正确的LaTeX格式,并且引用标记自然。注意避免使用Markdown,保持口语化但专业,同时符合用户的中文要求。</think>### 单链表操作实现心得与算分析 在实现单链表操作时,核心在于理解其动态内存管理和指针操作的特性。以下是具体分析: #### 1. **算复杂度分析** - **入/删除操作**:在已知节点位置时,时间复杂度为$O(1)$(如头部入);若需遍历查找目标节点(如按值删除),则时间复杂度为$O(n)$[^3]。 - **查找操作**:必须从头节点开始遍历,时间复杂度为$O(n)$。 - **内存管理**:动态分配节点需注意内存泄漏问题,删除节点后需及时释放内存[^1]。 #### 2. **改进方** - **尾指针优化**:添加尾指针(`tail`)可提升尾部入效率,使尾操作从$O(n)$优化为$O(1)$。 - **虚拟头节点**:引入虚拟头节点(`dummyHead`)可简化边界条件处理(如空链表或头节点操作)。 - **缓存长度信息**:维护链表长度变量`size`,避免频繁遍历统计长度。 - **双向链表扩展**:若需要频繁反向操作,可改用双向链表(但需额外空间存储前驱指针)[^1]。 #### 3. **经验教训** - **指针操作陷阱**:未正确处理指针指向可能导致链表断裂(如删除节点时未更新前驱节点的`next`)。 - **内存泄漏**:动态分配的节点未释放会造成内存泄漏,可通过工具如Valgrind检测[^3]。 - **边界测试**:需覆盖空链表、单节点链表、头尾节点操作等场景,例如: ```c // 示例:删除头节点时的错误处理 if (head != NULL) { Node* temp = head; head = head->next; free(temp); } ``` - **代码可读性**:合理封装函数(如`createNode()`, `insertAfter()`),避免重复代码[^1]。 #### 4. **实际应用场景** - 适用于频繁入/删除且数据量动态变化的场景(如实现队列、LRU缓存淘汰算)。 - 链式存储结构在操作系统文件系统、内存管理中有广泛应用[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值