单链表 (面试题)

关于单链表的基本操作,之前已经总结过了,那些掌握之后算是了解了单链表是什么?不过现在面试的题中,肯定不会只让你回答单链表的基础操作,总是会改变一些东西,或是扩展一下。

下面就是一些关于单链表的扩展内容:

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#pragma warning (disable:4996)
#define DataType int
typedef struct PNode{
 DataType data;
 struct PNode* next;
}Node,*PNode;
//创建新的节点
PNode BuyNode(DataType data);
//初始化单链表
void InitList(PNode* pHead);
//尾插
void PushList(PNode* pHead, DataType data);
//打印单链表
void PrintList(PNode pHead);
// 从尾到头打印单链表
void PrintListFromTail2Head(PNode pHead);
// 删除无头单链表的非尾结点
void DeleteNotTailNode(PNode pos);
// 在无头单链表非头结点前插入置为data的结点
void InsertNotHeadNode(PNode pos, DataType data);
// 用单链表实现约瑟夫环
PNode JosephCircle(PNode pHead, size_t M);
// 逆置单链表--三个指针
PNode ReverseList(PNode pHead);
// 逆置单链表--头插法
PNode ReverseList_P(PNode pHead);
// 对单链表进行冒泡排序--升序
void BubbleSort(PNode pHead);
// 查找单链表的中间结点,要求只能够遍历一次链表
PNode FindMidNode(PNode pHead);
// 查找单链表的倒数第K个结点,只能够遍历一次链表
PNode FindLastKNode(PNode pHead, size_t K);
//// 删除单链表的倒数第K个结点
//PNode DeleteLastKNode(PNode pHead, size_t K);
//
//// 合并两个已序单链表,合并之后依然有序
//PNode MergeList(PNode pHead1, PNode pHead2);

有些内容就不能按照常规的思路来看,我记得第一次上课的时候,老师出了一道智力题,

说是有两只分布不均匀的香,但是它们都能燃烧一个小时,如果我们想要测量一刻钟的时间,该如何做?

当时很多人都说将香掐成两段,然而,香并不是均匀的,所以不行。

最后给出了答案:将两只香同时点燃,不过,要一只点燃一头,另一只点燃两头,这样,等其中一只燃烧完了之后,时间刚好过了半个小时,再将另一头也点上,这样,剩余的香就能燃烧一刻钟的时间了。

同样的道理,这里的一些问题也是这样的想法,比如求中点的问题,只要给出两个指针,慢的一次走一步,快的一次走两步,等快的走到最后,那么慢的刚好走到中间。

下面就是这些函数的实现了:



#include"LinkList.h"
//创建新的节点
PNode BuyNode(DataType data)
{
 PNode Node = (PNode)malloc(sizeof(Node));
 if (Node)
 {
  Node->data = data;
  Node->next = NULL;
 }
 return Node;
}
//初始化单链表
void InitList(PNode * pHead)
{
 assert(pHead);
 (*pHead) = NULL;
}
//尾插
void PushList(PNode* pHead, DataType data)
{
 assert(pHead);
 PNode NewNode = BuyNode(data);
 if (NULL==(*pHead))
 {
  (*pHead) = NewNode;
 }
 else
 {
  PNode pCur = (*pHead);
  while (pCur->next)
  {
   pCur = pCur->next;
  }
  pCur->next = NewNode;
 }
}
void PrintList(PNode pHead)
{
 PNode pCur = pHead;
 while (pCur)
 {
  printf("%d ", pCur->data);
  pCur = pCur->next;
 }
 printf("\n");
}
// 从尾到头打印单链表
void PrintListFromTail2Head(PNode pHead)
{
 if (pHead)
 {
  PrintListFromTail2Head(pHead->next);//运用递归的思想,找出最后一个节点,打印
  printf("%d ", pHead->data);
 }
 printf("\n");
}
// 删除无头单链表的非尾结点,不能遍历单链表
void DeleteNotTailNode(PNode pos)
{
 if (NULL == pos)//如果pos的位置为空,直接返回
 {
  return;
 }
 PNode pDel = pos->next;//将pos后面的节点保存
 pos->data = pDel->data;//将pos后面的值,赋给pos中的data
 pos->next = pDel->next;//将pos的下一个位置指向待删除的下一个位置
 free(pDel);//释放空间
}
// 在无头单链表非头结点前插入置为data的结点
void InsertNotHeadNode(PNode pos, DataType data)
{
 if (NULL == pos)
 {
  return;
 }
 PNode NewNode = BuyNode(pos->data);
 if (NewNode)
 {
  NewNode->next = pos->next;
  pos->next = NewNode;
  pos->data = data;
 }
}
// 用单链表实现约瑟夫环
PNode JosephCircle(PNode pHead, size_t M)
{
 if (NULL == pHead)
 {
  return;
 }
 PNode pCur = pHead;
 while (pCur != pCur->next)
 {
  size_t k = M;
  while (--k)
  {
   pCur = pCur->next;
  }
  PNode pDel = pCur->next;
  pCur->data = pDel->data;
  pCur->next = pDel->next;
  free(pDel);
 }
 return pCur;
}
// 逆置单链表--三个指针
PNode ReverseList(PNode pHead)//不太理解
{
 if (NULL == pHead || NULL == pHead->next)
 {
  return pHead;
 }
 PNode prev = pHead;
 PNode pCur = prev->next;
 PNode pnext = pCur->next;
 while (pnext)
 {
  pCur->next = prev;
  prev = pCur;
  pCur = pnext;
  pnext = pnext->next;
 }
 pCur->next = prev;
 pHead->next = NULL;
 return pCur;
}
// 逆置单链表--头插法
PNode ReverseList_P(PNode pHead)
{
 if (NULL == pHead || NULL == pHead->next)
 {
  return NULL;
 }
 PNode pCur = pHead->next;
 PNode NewNode = NULL;
 while (pCur)
 {
  pHead->next = NewNode;
  NewNode = pHead;
  pHead = pCur;
  pCur = pCur->next;
 }
 pHead->next = NewNode;
 NewNode = pHead;
 return NewNode;
}
// 对单链表进行冒泡排序--升序
void BubbleSort(PNode pHead)
{
 if (NULL == pHead || NULL == pHead->next)
 {
  return;
 }
 PNode pCur = pHead;
 PNode pTail = NULL;
 DataType flag = 0;
 while (pTail != pHead)
 {
  pCur = pHead;
  while (pCur->next != pTail)
  {
   //结构体中的next定义成PNode*的形式,才能使next继续间接访问,
   if ((pCur->data) > (pCur->next->data)) 
   {
    DataType temp = pCur->data;         //交换
    pCur->data = pCur->next->data;
    pCur->next->data = temp;
    flag = 1;
   }
   pCur = pCur->next;
  }
  if (!flag)
  {
   return;
  }
  pTail = pCur;
 }
}
// 查找单链表的中间结点,要求只能够遍历一次链表
PNode FindMidNode(PNode pHead)
{
 if (NULL == pHead || NULL == pHead->next)
 {
  return;
 }
 //使用一快一慢两个指针,快的是慢的的二倍
 PNode pslow = pHead;
 PNode pfast = pHead;
 while (pfast&&pfast->next)//分两种情况考虑
 {
  pslow = pslow->next;
  pfast = pfast->next->next;
 }
 return pslow;//快的指针到尾部,慢的指针就在中间,所以返回慢的指针即可
}
// 查找单链表的倒数第K个结点,只能够遍历一次链表
PNode FindLastKNode(PNode pHead, size_t K)
{
 if (NULL == pHead || K == 0)
 {
  return NULL;
 }
 PNode pslow = pHead;
 PNode pfast = pHead;
 while (--K)//先让快的指针走K步
 {
  if (NULL == pfast)//如果K的值大于节点数,返回空
  {
   return NULL;
  }
  pfast = pfast->next;
 }
 while (pfast->next)//再一起走,等到快的走到尾部,慢的刚好到倒数第K个节点
 {
  pfast = pfast->next;
  pslow = pslow->next;
 }
 return pslow;//返回慢的指针即可
}
 //删除单链表的倒数第K个结点
PNode DeleteLastKNode(PNode pHead, size_t K)
{
 if (NULL == pHead || NULL == pHead->next)
 {
  return NULL;
 }
 PNode pos = FindLastKNode(pHead, K);
 Earse(pHead, pos);
}
 //合并两个已序单链表,合并之后依然有序
PNode MergeList(PNode pHead1, PNode pHead2)
{
 if (NULL == pHead1)
 {
  return pHead2;
 }
 if (NULL == pHead2)
 {
  return pHead1;
 }
 PNode pTail= NULL;
 PNode NewNode = NULL;
 if (pHead1->data < pHead2->data)
 {
  pTail = pHead1;
  pHead1 = pHead1->next;
 }
 else
 {
  pTail = pHead2;
  pHead2 = pHead2->next;
 }
 NewNode = pTail;
 while (pHead1&&pHead2)
 {
  if (pHead1->data < pHead2->data)
  {
   pTail->next = pHead1;
   pTail = pHead1;
   pHead1 = pHead1->next;
  }
  else
  {
   pTail->next = pHead2;
   pTail = pHead2;
   pHead2 = pHead2->next;
  }
 }
 if (pHead1)
 {
  pTail->next = pHead1;
 }
 else
 {
  pTail->next = pHead2;
 }
 return NewNode;
}

#include"LinkList.h"
void FunTest()
{
 PNode pHead;
 InitList(&pHead);
 PushList(&pHead,5);
 PushList(&pHead, 8);
 PushList(&pHead, 2);
 PushList(&pHead, 7);
 PushList(&pHead, 9);
 PrintList(pHead);
 PrintListFromTail2Head(pHead);
 //
 //JosephCircle(pHead, 3);
 //PrintListFromTail2Head(pHead);
 PNode p=FindMidNode(pHead);
 printf("%d\n", p->data);
 PNode p1 = FindLastKNode(pHead, 1);
 printf("%d\n", p1->data);
 BubbleSort(pHead);
 PrintList(pHead);
}
int main()
{
 FunTest();
 system("pause");
 return 0;
}

程序写的很欠缺,有的地方还需再进行,如果,你们有什么意见或建议,请评论……

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值