c实现单链表面试题

来源:互联网 发布:centos 不能显示中文 编辑:程序博客网 时间:2024/05/17 01:19

在面试中,链表题出现的频率也是相当的高,以下是对链表题的一个总结,归纳:


1 .从尾到头打印单链表
2.删除⼀个⽆头单链表的⾮尾节点
3.在⽆头单链表的⼀个⾮头节点前插⼊⼀个节点
4.单链表实现约瑟夫环
5.逆置/反转单链表
6.单链表排序(冒泡排序&快速排序)
7.合并两个有序链表,合并后依然有序
8.查找单链表的中间节点,要求只能遍历⼀次链表
9.查找单链表的倒数第k个节点,要求只能遍历⼀次链表
10.判断单链表是否带环?若带环,求环的长度?求环的⼊⼜点?并计算每个算法
的时间复杂度&空间复杂度。
11.判断两个链表是否相交,若相交,求交点。(假设链表不带环)
12.判断两个链表是否相交,若相交,求交点。(假设链表可能带环)【升级版】

具体代码如下


typedef int DataType;//数据类型的重定义typedef struct Node{DataType _data;struct Node* next;//指向下一个结点的指针}Node,*pNode,*pList;void InitLinkList(pList* pplist)  //链表初始化函数{    assert(pplist);    *pplist = NULL;}pNode BuyNode(DataType x)//新建一个结点{    pNode  pnode=malloc(sizeof(Node));if(pnode==NULL){perror("PushBack()::malloc");//内存开辟失败exit(1);}pnode->next=NULL;pnode->_data=x;return pnode;}void PushBack(pList *pplist,DataType x)//在单链表的尾部插入一个元素{ pNode pnode=NULL; assert(pplist); pnode=BuyNode(x);if(*pplist==NULL)//链表为空{      *pplist=pnode;}else//找到尾结点,在其后面插入{pNode cur=*pplist;while(cur->next)        {cur=cur->next;}        cur->next=pnode;}}void PopBack(pList *pplist)//删除尾部结点{pNode cur=NULL;assert(pplist);if(*pplist==NULL)//空链表{return;}else if((*pplist)->next==NULL)//只有一个结点{free(*pplist);*pplist=NULL;}else //两个或两个以上结点{    cur=*pplist;//在单链表中删除一个结点需找到其前一个结点         while((cur->next)->next)//查找尾部结点的前一个结点      {     cur=cur->next;      }     free(cur->next);//此时cur->next指向尾部结点     cur->next=NULL;}}void PushFront(pList *pplist,DataType x)//首部插入结点{pNode pnode=NULL;    assert(pplist);pnode=BuyNode(x);if(*pplist==NULL){*pplist=pnode;}else{pnode->next=*pplist;//插在头部结点之前*pplist=pnode;    }}void PopFront(pList *pplist)//首部结点的删除{  pNode del=NULL;    assert(pplist);del=*pplist;if(*pplist==NULL){return;}     *pplist=del->next; free(del); del=NULL;//将del置空,防止其成为野指针}void BubbleSort(pList* pplist)//冒泡排序{pNode cur=NULL;pNode tail=NULL;    assert(pplist);if(*pplist==NULL &&(*pplist)->next==NULL)//若单向链表为空或只有一个元素时,不进行排序{return;}while(tail != (*pplist)->next)//控制排序的趟数{        cur=*pplist;//每次比较都从头部开始    while(cur!=tail && ( cur->next!=tail))//每趟中的比较次数    {   if(cur->_data > (cur->next)->_data)   {   DataType tmp=cur->_data;   cur->_data=(cur->next)->_data;   (cur->next)->_data=tmp;   }   cur=cur->next;     } tail=cur;//尾部结点为比较的最后一个元素}//执行完一趟后,tail向前跳转}void ReversePrint(pList plist) //逆序打印单项链表{pNode cur=plist;if(plist==NULL)    {return;}if(cur->next)//寻找尾部结点{ReversePrint(cur->next);//递归    }printf("%d",cur->_data);}pNode Find(pList plist,DataType x)//查找某个元素{pNode cur=plist;if(cur==NULL){return NULL;}else{while(cur&&(cur->_data!=x))//从前往后依次遍历整个链表{          cur=cur->next;}if(cur!=NULL){return cur;//返回结点位置}return NULL;//找不到返回空}}void EraseNotTail(pNode pos)//删除无头单链表的非尾结点 {pNode del=NULL; //将指定位置处的结点,将其后一个结点的数据赋给指定位置处的数据,然后将其后一个结点删除if(pos==NULL){return;}if(pos->next){pos->_data=(pos->next)->_data;del=pos->next;pos->next=del->next;free(del);del=NULL;}}//在无头单链表的非头结点前插入一个元素 void InsertFrontNode(pNode pos, DataType x)//思路:在指定位置的后面插入一个元素,它们的数据进行交换{pNode pnode=BuyNode(x);DataType tmp;if(pos==NULL){return;}pnode->next=pos->next;pos->next=pnode;    tmp=pos->_data;    pos->_data=pnode->_data;pnode->_data=tmp;}void JosephCycle(pList* pplist, int k)//约瑟夫环问题 {pNode cur=NULL;pNode del=NULL;int i=0;assert(pplist);if(*pplist==NULL){return;}cur=*pplist;while(cur!=cur->next){for(i=0;inext;  }  printf("%d ",cur->_data);  cur->_data=(cur->next)->_data;  del=cur->next;  cur->next=del->next;  free(del);  del=NULL;}printf("%d",cur->_data);}void ReverseList(pList* pplist)//逆序单向链表  {pNode cur=NULL;pNode next=NULL;pNode tmp=NULL;assert(pplist);if((*pplist==NULL) && ((*pplist)->next==NULL)){return;}cur=*pplist;next=cur->next;cur->next=NULL;while(next){tmp=next->next;next->next=cur;cur=next;next=tmp;}*pplist=cur;}pList Merge(const pList* p1, const pList* p2)//合并两个有序列表 {pList newlist=NULL;pList list1=NULL;pList list2=NULL;pList tail=NULL;    assert(p1&&p2);list1=*p1;list2=*p2;if(list1==list2)//list1与list2为同一条链表,或都为空链表{return NULL;    }if(list1==NULL)//一条为空,另一条不为空{return list2;}if(list2==NULL){return list1;} if(list1->_data_data)//新链表的首部  {  newlist=list1;   list1=list1->next;  } else {  newlist=list1;   list1=list1->next; } tail=newlist;//新链表的尾部while(list1 && list2)    {   if(list1->_data_data)  { tail->next=list1; list1=list1->next; tail=tail->next;   }  else  {tail->next=list2;list2=list2->next; tail=tail->next;   }}if(list1==NULL){tail->next=list2;}else{tail->next=list1;}return newlist;}//查找单链表的中间节点,要求只能遍历一次链表 pNode FindMidNode(pList plist){//定义两个指针分别为fast和slow,fast每次跳两下,slow每次一下,//当fast指向链表尾部时,slow所指的位置就是中间结点    pNode fast=plist;    pNode slow=plist;    while((fast) && (fast->next))//链表的结点个数存在奇数和偶数{fast=(fast->next)->next;slow=slow->next;}return slow;}//查找单链表的倒数第k个节点,要求只能遍历一次链表 pNode FindKNode(pList plist, int k){//定义两个指针分别为fast和slow,//使fast先走k-1步,之后slow再走,当fast指向尾部时,slow所指的就是倒数第k个元素pNode fast=plist;pNode slow=plist;    while(fast && fast->next){if(--k<=0){   slow=slow->next;  }fast=fast->next;}if(k<=0){return slow;}return NULL;}//查找单链表的倒数第k个节点,要求只能遍历一次链表 pNode FindKNode(pList plist, int k){  pNode fast=plist;pNode slow=plist;int i=0;for(i=0;inext){fast=fast->next;}else{break;}}if(inext){fast=fast->next;slow=slow->next;}return slow;}}pNode CheckCircle(pList plist) //判断链表是否带环 {    pNode fast=plist;pNode slow=plist;while(fast && fast->next)//当fast=slow时代表有环{fast=(fast->next)->next;slow=slow->next;if(fast==slow){return fast;}    }return NULL;}int GetCircleLength(pNode meet) //求环的长度{  //从相遇点转一圈的距离pNode pnode=meet->next;//meet为fast和slow的相遇点int i=1;while(pnode!=meet){pnode=pnode->next;i++;}return i;}pNode GetCycleEntryNode(pList plist, pNode meet) //求环的入口点 {pNode pnode=plist;if((plist==NULL)&&(meet==NULL)){return NULL;}while(pnode!=meet){meet=meet->next;pnode=pnode->next;}return meet;     }int CheckCross(pList list1, pList list2)//判断两条单链表是否相交  {pNode p1=list1;pNode p2=list2;while(p1 && p1->next){p1=p1->next;}while(p2 && p2->next){p2=p2->next;}if((p1==p2)&&(p1!=NULL)){return 1;}return -1;}pNode GetCrossNoCycle(pList list1, pList list2)//转化成不带环的链表求解  {   pNode meet=NULL;pNode cur=list1;pNode crossNode=NULL;while(cur&&cur->next){cur=cur->next;}cur->next=list2;    meet=CheckCircle(list1);     crossNode=GetCycleEntryNode(list1,meet);return crossNode;}pNode GetCycleFrontEntryNode(pList list,pNode meet)//求入口点的前一个结点{pNode cur=list;pNode p=GetCycleEntryNode(list,meet);//环的入口点while(cur->next!=p){   cur=cur->next;}return cur;}//在两个链表已经相交的前提下,转化成不带环的链表求解 pNode GetCrossNode(pList list1, pList list2) //求交点{pNode p1=CheckCircle(list1);//判断是否带环,相遇点    pNode p2=CheckCircle(list2);//判断是否带环pNode crossNode=NULL;if(p1==NULL && p2==NULL)//list1不带环{crossNode=GetCrossNoCycle(list1,list2);return crossNode;}   else if (p1&&p2)                    //如果两个链表都带环      {          pNode endNode= NULL;          pNode cur= NULL;        endNode=GetCycleFrontEntryNode(list1,p1);//找到环入口的前一个结点          cur=endNode->next; //保存环的入口          endNode->next = NULL; //将环断开拆分成两个不带环的链表          crossNode=GetCrossNoCycle(list1,list2); //获得交点          endNode->next = cur;                         //复原链表          } return crossNode;}void Display(pNode plist){pNode cur=plist;while(cur){printf("%d->",cur->_data);cur=cur->next;}printf("NULL\n");}void Destory(pNode *pplist){pNode del=NULL;pNode cur=NULL;    assert(pplist); del=*pplist;     cur=*pplist; while(cur) { del=cur; cur=cur->next; free(del); } del=NULL; *pplist=NULL;}








原创粉丝点击