单链表常见面试题(一)
来源:互联网 发布:php 生成文本文件 编辑:程序博客网 时间:2024/06/03 20:10
1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?
顺序表:类似于数组结构。是连续存储的。在读取的时候比较快。但是在插入和删除时移动的数据量比较大,非常麻烦。顺序表在开辟空间时在满的时候重新申请开辟大的空间,会存在空间浪费。
链表:是链式结构。对于插入和删除操作比较方便。在开辟空间时对单个节点申请空间,不会造成空间的浪费。
首先我们时间上来进行分析:
(1)对于顺序表。不论是静态的还是动态的,他们都是连续的存储空间,在读取上时间效率比较快,可以通过地址之间的运算来进行访问,但是在插入和删除操作会出现比较麻烦的负载操作。
(2)对于链表,因为他是链式存储。在我们需要的时候才在堆上开辟空间,对于插入查找的方式比较便携。但是对于遍历的话需要多次的空间跳转。
顺序表多用于遍历操作频繁时使用,链表多用于在删除插入多的时候使用。
2.从尾到头打印单链表
这个问题我们使用递归的思想来解决。从头结点开始,在打印头结点数据前先打印它前一个节点数据,以此类推,首先打印最后一个节点数据,调用结束返回上一层。
void RePrintf(Node* pList)//2逆序打印{if (pList){RePrintf(pList->next); //递归调用printf("%d->", pList->data);}}
3.删除一个无头单链表的非尾节点
在这个问题上,要保证删除后前后节点依旧能够连接。但在单链表中,我们无法找到要删除的结点的前一个节点,但是我们可以找到下一个。因此交换当前要删除的结点和下一个节点的数据。再把前后链接关系写上,就可以来解决。
我们在这里本来是删除cur,这里用next替换删除。
void EraseNontail(Node**pList, Node* pos)//删除无头单链表的非尾节点{assert(pos);assert(*pList);Node* cur = pos->next;pos->data=cur->data ;pos->next = cur->next;free(cur);cur = NULL;}
4.在无头单链表的一个节点前插入一个节点
在插入节点时,我们也要把插入后的前后链接关系写清楚。所以依旧用替换法。本来是插入到pos节点,但我们找到pos的next节点。交换数据。
void InsertNonHead(Node**pList, Node* pos,DataType x)//4无头单链表前插入{assert(pos);assert(*pList);Node* cur = BuyNode(x);Node* next = pos->next;DataType tmp = cur->data;cur->data = pos->data;pos->data = tmp;pos->next = cur;cur->next = next;}
5.单链表实现约瑟夫环
Node* JosephRing(Node* pList, int k)//5约瑟夫环{Node* cur = pList;Node* next = NULL;Node* tail = pList;while (tail->next){tail = tail->next;}tail->next = pList;while (cur->next != cur){int count = k;while (--count){cur = cur->next;} next = cur->next;cur->data = next->data;cur->next = next->next;free(next);next = NULL;}return cur;}
6.逆置/反转单链表
void ReList(Node** pList)//6逆置反转单链表{if (*pList == NULL){return 0;}Node* cur = *pList;*pList = NULL;while (cur){Node* tmp = cur;cur = cur->next;PushFront(pList, tmp->data);//头插到pList中}}7单链表排序(冒泡排序&快速排序)
设置一个tail,用来表明已经有序的界限。每次把cur和next进行比较。若next->data 大于 cur->data,则交换两个值。继续走,直到遇到tail
void SortList(Node* pList)// 7冒泡排序{if (pList == NULL || pList->next == NULL){return;}Node* tail = NULL;while (tail != pList)//总体循环条件 一共排序多少次{Node* cur = pList;Node* next = cur->next;int flag = 0;while (next != tail) //在每一次中的循环条件 {if (cur->data > next->data){int data = cur->data;cur->data = next->data;next->data = data;flag = 1;}cur = next;next = cur->next;}tail = next;if (flag == 0) //用来优化冒泡排序,若flag值没有变化,则表明已经有序。直接return{ return;}}}
8合并两个有序链表,合并后依然有序
Node* Merge(Node* List1, Node* List2)//8合并两个有序单链表{if (List1 == NULL) //如果List1为空,则返回List2{return List2;}else if(List2 == NULL) //如果List2为空,则返回List1{return List1;}else{//找出新链表的头结点 此时List1和List2都不为空,比较两个链表第一个节点的值,新链表指向值较小的那个链表Node* head = NULL;if (List1->data > List2->data){head = List2; List2 = List2->next; //此时,新链表指向List2}else{head = List1;List1 = List1->next; //此时,新链表指向List1}//尾插Node* tail = head;while (List1&&List2) //List1和List2都不为空{if (List1->data <List2->data) 选择List1和List2中指向节点中值较小的那个节点,链接到新链表中{tail->next= List1;List1 = List1->next;}else{tail->next= List2;List2 = List2->next;}tail = tail->next;}
//while循环出来,可能是List1为空或者List2为空。把不为空的链表直接链接到新表的尾if (List1){tail->next = List1;}else{tail->next = List2;}return head;}}
9.查找单链表的中间节点,要求只能遍历一次链表
这里我们使用快慢指针。快指针每次比慢指针多走一步。当fast走到最后时,slow当好指向是中间节点 。
当节点数为偶数个,slow指向中间后面的那个。
当节点数为奇数个,slow刚好指向最中间。
Node* FindMiddle(Node* pList)//9遍历一遍找中间数{if (pList == NULL){return NULL;}Node* slow = pList;Node* fast = pList;while (fast&&fast->next){slow = slow->next;fast = fast->next->next;}return slow;}10.查找单链表的倒数第k个节点,要求只能遍历一次链表
求倒数第K个,同样使用快慢指针。不过让快指针先走K-1.步,此时再让快慢指针同时走。当快指针走到最后一个节点,慢指针刚好走到倒数第K个
Node* CountBackward(Node* pList, int k)//10找倒数第K个节点{Node* fast = pList;Node* slow = pList;while (--k) //让快指针先走K-1{fast = fast->next;}while (fast&&fast->next){fast = fast->next;slow = slow->next;}return slow;}
- [ 面试题 ] 常见面试题 (一)
- 单链表常见面试题(一)
- 常见面试题(一)
- 常见面试题(一)
- 常见面试题一
- c语言常见面试题(一)
- java常见的面试题(一)
- JDBC常见面试题集锦(一)
- JDBC常见面试题集锦(一)
- JDBC常见面试题集锦(一)
- JDBC常见面试题集锦(一)
- Java基础 常见面试题(一)
- Android常见面试题(一)
- PHP常见面试题(一)
- 数据库常见面试题(一)
- 常见网络编程面试题(一)
- 常见Android面试题(一)
- Java常见面试题汇总(一)
- caffe环境配置+ubuntu14.04
- pthread_join和pthread_detach的用法
- CNCC 2016 | 山世光:深度化的人脸检测与识别技术—进展与展望
- Ford-Fulkerson算法求最大流Java实现
- linux源码安装 ubuntu安装vim为例
- 单链表常见面试题(一)
- Linux 文件系统的目录
- 乱码问题!Eclipse 的控制台console必须用GBK编码。【转载】 Eclipse 的控制台必须用GBK编码。所以条件1和条件4必须同时满足否则运行的还是乱码。才能保证不是乱码。
- Finger Search Tree 模板 BZOJ3224
- Android 下拉刷新框架实现
- HI3520D在内核中复用UART2,UART3管脚
- scrollview嵌入webview导致自动滚动
- Git 保存用户名和密码
- linux驱动编程小技巧