链表面试题

1、单链表的创建、插入节点、删除节点、反转等基本操作。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<iostream>
#include<string.h>
typedef struct Listnode
{
	int data;
	struct Listnode* pnext;
}node,*pnode;
pnode Creatlist()
{
	pnode phead = (pnode)malloc(sizeof(node));
	phead->data = 2;
	phead->pnext = NULL;
	int len = 0;
	int value = 0;
	pnode pTail = phead;
	printf("input data len");
	scanf("%d",&len);
	for (int i = 0; i < len; i++)
	{
		pnode pnew = (pnode)malloc(sizeof(node));
		printf("input value");
		scanf("%d",&value);//一定要带取址符号
		pnew->data = value;
		pTail->pnext= pnew;
		pnew->pnext = NULL;
		pTail = pnew;
	
	}
	return phead;
}
void Printlist(pnode phead)
{
	if (phead == NULL) return;
	pnode p = phead;
	while (p->pnext != NULL)
	{
		printf("node's value is%d\n",p->pnext->data);
		p = p->pnext;
	}
}
int Getlengthoflist(pnode phead)
{
	if (phead == NULL)return 0;
	int length = 0;
	pnode p = phead->pnext;
	while (p != NULL)
	{
		length++;
		p = p->pnext;
    }
	return length;

}
int Delenode(pnode phead, int pos)//删除节点时,头结点和尾节点要分开处理
{
	if (phead == NULL)return 0;
	int len = Getlengthoflist(phead);
	pnode p = phead;
	int result = 0;
	if (pos == 0)   //删除头结点
	{
		p->pnext = NULL;
		result = -1;
		return result;
	}
	if (pos == len)//删除尾节点
	{
		while (pos != 1)
		{
			pos--;
			p = p->pnext;
		}
		pnode deletnode = p->pnext;
		result = deletnode->data;
		p->pnext = NULL;
		free(deletnode);
		return result;
	}
	if ((pos > 0) && (pos <len))
	{
		while (pos != 1)
		{
			pos--;
			p = p->pnext;
		}
	}
	pnode delenode = p->pnext;
	p->pnext = delenode->pnext;
	result = delenode->data;
	free(delenode);
	return result;

}
/*pnode Deltvaluenode(pnode phead, int value)// 删除链表中节点值等于value的节点
{
	pnode cur = phead;
	pnode pre = NULL;	
	pnode temp = NULL;
	while (cur!=NULL)
	{
		if (cur->pnext != NULL)
		{
			if (cur->pnext->data == value)// 这样写有错,要是最后一个节点的值是VALUE呢?会出错
			{
				pre = cur;
				temp = cur->pnext;
				pre->pnext = temp->pnext;
				free(temp);
				temp = NULL;
            }
			else
				cur = cur->pnext;
		}
		else
		{
			if (cur->data == value){"找不到上一个节点"}

		}

	}
   return phead;
}*/
pnode Deltvaluenode(pnode phead, int value)// 删除链表中节点值等于value的节点
{
	pnode cur = phead;
	pnode pre = NULL;
	pnode temp = NULL;
	while (cur != NULL)
	{
		if ((pre == NULL) && (cur->data == value))
		{
			pre = phead; 
			free(pre);
			pre = NULL;
			cur = cur->pnext;
			phead = cur;
		}
		if (cur->data == value)
		{
			pre->pnext = cur->pnext;
			free(cur);
			cur = pre->pnext;
		}
		else
		{
			pre = cur;
			cur = cur->pnext;
		}
	}
	return phead;
}
pnode Insertlist(pnode phead,int pos,int value)//在pos之后插入节点
{
	int len = Getlengthoflist(phead);
	pnode p = phead;
	pnode pnew = (pnode)malloc(sizeof(node));
	pnew->data = value;
	pnew->pnext = NULL;
	if ((pos >=0) && (pos < len))
	{
		while (pos != 0)
		{
			pos--;
			p = p->pnext;
		}
		pnew->pnext = p->pnext;
		p->pnext = pnew;         //这两句话的顺序不可以颠倒	
	}
	if (pos == len)
	{
		while (pos != 0)
		{
			pos--;
			p = p->pnext;
		}
		pnew->pnext = NULL;
		p->pnext = pnew;

	}
	return phead;
}
 pnode InsertNode(pnode phead,int value)//在有序的链表中插入一个新的节点,
{
	 pnode cur=phead;
	 pnode pre=NULL;
	 while((cur!=NULL)&&cur->data<value)
	 {
		 pre = cur;
		 cur = cur->pnext;
	 }
	 pnode pnew = (pnode)malloc(sizeof(node));
	 pnew->data = value;
	 pnew->pnext = NULL;
	 if (pre != NULL)
	 {
		 pre->pnext = pnew;
		 pnew->pnext = cur;
		 return phead;
	 }
	 else
	 {
		 pnew->pnext = cur;
		 return pnew;
	 }	 
}
 pnode sortlist(pnode phead)//链表的冒泡排序
 {
	 int len = Getlengthoflist(phead);
	
	 for (int i = 0; i < len-1; i++)
	 {
         pnode p = phead->pnext;
		 for (int j = 0; j < len - i - 1; j++)
		 {
			 if (p->data <= p->pnext->data)
				 p = p->pnext;
			 else
			 {
				 int temp = p->data;
				 p->data = p->pnext->data;
				 p->pnext->data = temp;
				 p = p->pnext;
			 }
		 }
	 }
	 return phead;
 
 }
 pnode reverselist(pnode phead)//反转链表,改变链表的结构. 需要三个指针
 {
	// pnode prehead =NULL;
	 pnode cur = phead->pnext;
	 pnode P_next = NULL;
	 pnode P_pre = NULL;
	 while (cur != NULL)
	 {
		 P_next = cur->pnext;//一定要先保存下来下一个节点
		 if (P_next == NULL)
		 {
			 phead->pnext= cur;
		 }
		 cur->pnext = P_pre;
		 P_pre = cur;
		 cur = P_next;
	 }
	 return phead;
 }
Status InitList1(LinkList &L)    //等价于Node *L  
 {
	 L = (LinkList)malloc(sizeof(node)); /* 产生头结点,并使L指向此头结点 */
	 if (!L) /* 存储分配失败 */
		 return 0;
	 L->pnext = NULL; /* 指针域为空 */


	 return 1;
 }


 //初始化表头,用二级指针  
 Status InitList2(LinkList *L)   //等价于Node **L  
 {
	 *L = (LinkList)malloc(sizeof(node)); /* 产生头结点,并使L指向此头结点 */
	 if (!(*L)) /* 存储分配失败 */
		 return 0;
	 (*L)->pnext = NULL; /* 指针域为空 */


	 return 1;
 }
 Status ClearList2(LinkList L)
 {
	 LinkList p, q;
	 p = L->pnext;           /*  p指向第一个结点 */
	 while (p)                /*  没到表尾 */
	 {
		 q = p->pnext;
		 free(p);
		 p = q;
	 }
	 L->pnext = NULL;        /* 头结点指针域为空 */
	 return 1;
 }
 Status ListInsert2(LinkList L, int i, int e)
 {
	 int j;
	 LinkList p, s;
	 p = L;
	 j = 1;
	 while (p && j < i)     /* 寻找第i个结点 */
	 {
		 p = p->pnext;
		 ++j;
	 }
	 if (!p || j > i)
		 return 0;   /* 第i个元素不存在 */
	 s = (LinkList)malloc(sizeof(node));  /*  生成新结点(C语言标准函数) */
	 s->data = e;
	 s->pnext = p->pnext;      /* 将p的后继结点赋值给s的后继  */
	 p->pnext = s;          /* 将s赋值给p的后继 */
	 return 1;
 }
 Status ListTraverse(LinkList L)
 {
	 LinkList p = L->pnext;
	 while (p)
	 {
		 printf("%d",p->data);
		 p = p->pnext;
	 }
	 printf("\n");
	 return 1;
 }
int main()
{
	int deledata = 0;
	pnode plist = Creatlist();
	Printlist(plist);
	//plist = Insertlist(plist, 3, 6);
	//Printlist(plist);
	printf("\n\n");
	//plist = InsertNode(plist, 1);
	//Printlist(plist);
	//plist=sortlist(plist);
	plist = reverselist(plist);
	Printlist(plist);
	//plist = Insertlist(plist, 0, 6);
	//Printlist(plist);
	//printf("\n\n");
	//plist = Insertlist(plist, 5, 6);
	//Printlist(plist);
	//deledata=Delenode(plist,3);
	//Printlist(plist);
	//printf("deledata is%d",deledata);
	//deledata = Delenode(plist, 5);
	//Printlist(plist);
	//printf("deledata is%d", deledata);
	//deledata = Delenode(plist, 0);
	//Printlist(plist);
	//printf("deledata is%d", deledata);
	//plist = Deltvaluenode(plist, 3);
	//Printlist(plist);

	system("pause");

}

2、给定一个链表和一个节点的指针,定义一个在O(1)时间内删除该节点的函数。

删除节点思路有二:常规的做法是找到待删节点的前一个节点

第二:不用找到待删节点的前一个节点,而是把待删节点i的后一个节点J中的内容复制到节点i内,然后再把i节点的next指向节点J的下一个节点,再删除节点J.

还有一个问题,如果基于第二思路,当删除的节点是链表的尾节点时,我们还是需要顺序遍历链表,找到尾节点的前一个节点。

3、链表的初始化和销毁时,要用到二级指针或者一级指针的引用。

简单来说,修改头指针则必须传递头指针的地址,否则传递头指针即可。这与普同的变量类似,当需要修改变量的值时,需要传递其地址,否则传递普通变量即可。使用二级指针,可以很方便的修改传入的一级指针的值。如果用一级指针,则只能通过指针修改指针所指向的内容,无法修改指针的值,也就是指针所指向的内存的内容,所以初始化链表和销毁链表时 需要二级指针或者一级指针的引用。

4/判断链表是否有环?以及环的入口位置?

bool Iscirclelist(pnode phead)
{
if (phead == NULL)return false;
pnode cur = phead->pnext;
while (cur)
{
if (cur->pnext == phead)return true;
cur = cur->pnext;

}
return false;
}
bool Iscirclist1(pnode phead)
{
if (phead == NULL)return false;
pnode plow =phead->pnext;
pnode pquick = phead->pnext->pnext;
while (pquick != NULL&&pquick->pnext != NULL)
{
pquick = pquick->pnext->pnext;
plow = plow->pnext;
if (pquick == plow)
return true;
}
return false;

}

//如何来确定循环链表的入口地址
//环的接入点:碰撞点p到连接点的距离 = 头指针到连接点的距离,因此,分别从碰撞点、头指针开始走,
//相遇的那个点就是连接点。
class Solution {
public:
    ListNode* EntryNodeOfLoop(ListNode* pHead)
    { ListNode* fast,*slow;
      fast=pHead;
      slow=pHead;
     while(fast!=NULL&&fast->next!=NULL)
     {
         fast=fast->next->next;
         slow=slow->next;
         if(fast==slow)
         {    fast=pHead;

          while(fast!=slow)
          {
              fast=fast->next;
              slow=slow->next;
          }
          if(slow==fast)
              return slow;
         }
     }
      return NULL;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值