C语言实现单链表-面试题(基础篇)

来源:互联网 发布:搜狐网络大厦一层图片 编辑:程序博客网 时间:2024/06/05 01:50

单链表的实现(点击打开链接)

单链表简易实现后有如下面试题

1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用?
2.从尾到头打印单链表
3.删除一个无头单链表的非尾节点
4.在无头单链表的一个节点前插入一个节点
5.单链表实现约瑟夫环
6.逆置/反转单链表
7.单链表排序(冒泡排序&快速排序)
8.合并两个有序链表,合并后依然有序
9.查找单链表的中间节点,要求只能遍历一次链表
10.查找单链表的倒数第k个节点,要求只能遍历一次链表

1.比较顺序表和链表的优缺点,说说它们分别在什么场景下使用? 

顺序表:内存中地址连续
长度不可变更
支持随机查找 可以在O(1)内查找元素
适用于需要大量访问元素的 而少量增添/删除元素的程序
链表 :内存中地址非连续
长度可以实时变化
不支持随机查找 查找元素时间复杂度O(n)
适用于需要进行大量增添/删除元素操作 而对访问元素无要求的程序


结构体的定义

typedef int DataType;typedef struct ListNode{DataType data;struct ListNode *next;}ListNode;


2.从尾到头打印单链表 

函数实现

void TaliToHead(ListNode *plist)//从尾到头打印单链表{if(plist == NULL)return;TaliToHead(plist->next);printf("%d->",plist->data);}
3.删除一个无头单链表的非尾节点 

void DeleteNoHead(ListNode **pos)//删除一个无头单链表的非尾节点{ListNode * cur = *pos;ListNode *prel = cur;while(cur->next)//从该节点从前往后覆盖,并删除最后一个节点{prel = cur;cur->data = (cur->next)->data;cur = cur->next;}free(prel->next);prel->next = NULL;}
4.在无头单链表的一个节点前插入一个节点 

void InsertNoHead(ListNode **pos, DataType x)//无头单链表的一个节点前插入一个节点{ListNode *cur = *pos;ListNode *ptemp = BuyNode(x);assert(*pos);ptemp->next = cur->next;cur->next = ptemp;ptemp->data = cur->data;cur->data = x;}
5.单链表实现约瑟夫环

void JosephRing(ListNode **pplist,DataType x)//约瑟夫环,x为间隔{ListNode *cur = *pplist;ListNode *prel = *pplist;ListNode *ptem = NULL;if(NULL == *pplist || NULL == (*pplist)->next)return;while(cur->next){cur = cur->next;}cur->next = prel;//将单链表的首尾节点连起来成环。cur = *pplist;while(cur->next!=cur){DataType n = x;while(n--){prel = cur;cur = cur->next;}prel->next = cur->next;free(cur);cur = prel->next;}printf("%d\n",cur->data);//最后剩下的节点}

6.逆置/反转单链表 

void ReverseList(ListNode **pplist)//逆序单链表{ListNode *cur = *pplist;ListNode *ptemp = NULL;ListNode *ret = NULL;if(NULL == *pplist || NULL == (*pplist)->next)return;while(cur){ptemp = cur;cur = cur->next;ptemp->next = ret;ret = ptemp;}*pplist = ret;}
7.单链表排序(冒泡排序&快速排序)

 

void SortList(ListNode *plist)//冒泡排序单链表{ListNode *tail = NULL;if(NULL == plist || NULL == (plist)->next)return;while(plist->next != tail){ListNode *cur = plist;ListNode *next = cur->next;while(next != tail){if(cur->data < next->data){DataType temp = cur->data;cur->data = next->data;next->data = temp;}cur = next;next = next->next;}tail = cur;}}


8.合并两个有序链表,合并后依然有序

void ListToList(ListNode **pplist,ListNode **pplist1)//合并两个单链表{ListNode *cur = *pplist;if(NULL == cur){cur = *pplist1;}else{while(cur->next)cur = cur->next;cur->next = *pplist1;}}
合并后再用一个上面的排序函数即可
 
9.查找单链表的中间节点,要求只能遍历一次链表 

ListNode *MidOfList(ListNode *plist)//查找中间节点{ListNode *fast = plist;//快指针一次过两个节点ListNode *slow = plist;//慢指针一次过一个,快指针到尾节点,慢指针就到中间节点if(NULL == plist || NULL == plist->next)return plist;else{while(fast && fast->next){slow = slow->next;fast = fast->next->next;}}return slow;}



10.查找单链表的倒数第k个节点,要求只能遍历一次链表

和上面找中间相似

ListNode *FindNum(ListNode *plist,DataType x)//查找单链表中倒数第x个节点{ListNode *fast = plist;ListNode *slow = plist;if(NULL == plist || NULL == plist->next)return plist;while(x--)//快指针先跑x个节点{fast = fast->next;}while(fast && fast->next)//快指针到尾节点是,慢指针刚好到倒数第X个节点{slow = slow->next;fast = fast->next;}return slow;}

以上函数为简单思路,有待优化和提升,测试过没什么大问题,有大问题联系我。。尴尬