链表面试题

头文件 “Link.h”

#ifndef __LINKLIST_H__
#define __LINKLIST_H__
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DataType;
typedef struct Node
{
	int data;
	struct Node* next;
}*pList,*pNode,*pLinkNode;


void ListToheadFromLastD(pList plist);   //递归
void ListToheadFromLast(pList* pplist);   //从尾到头打印,非递归
void EraseNotTailNode(pList* pplist,pNode pos);      //删除一个无头单链表的非尾节点 
void InsertNodeNoHead(pList* pplist,pNode pos,int d);      //在一个无头单链表的一个节点前插入一个节点
void JosephCricle(pList* pplist, int d);       //约瑟夫环
void BubbleSort(pList plist);     //冒泡排序
void SelectSort(pList plist);            //选择排序
void myQuickSort(pList pStart,pList pEnd);       //快速排序
pNode AddSort(pList* pplist1, pList* pplist2);     //合并两个有序链表,结果依然有序,递归
pNode FindNode(pList plist,int d);      //查找单链表的中间节点
pNode FindFromtail(pList plist, int k);   //查找单链表倒着数第k个元素
void rmNodeFromTail(pList* pplist, int k);           //删除倒数第k个元素
void UnionSet(pList plist1, pList plist2);       //求两个已排序单链表中相同的元素
pLinkNode CheckCycle(pList plist);           //判断链表是否带环
int GetCircleLength(pLinkNode meet);         //求环的长度
pLinkNode GetCycleEntryNode(pList list, pLinkNode meetNode);          //求环的入口点
pNode CheckCross(pList list1, pList list2);     //判断两个链表是否相交,若相交求交点
pNode PanDuanSuper(pList p1, pList p2);     //判断升级版

void DestroyList(pList plist);           //销毁链表
pNode BuyNode(int d);
pNode CreatList(pList* pplist, int d);   //创建一个连续的连续的链表
void PushBack(pList* pplist, int d);     //尾插
void Print(pList plist);				 //打印
#endif __LINKLIST_H__

1.从尾到头打印单链表(递归)

void ListToheadFromLastD(pList plist)    //从尾到头打印,递归
{
	pNode cur = plist;
	if (plist == NULL)
		return;
	if (cur->next == NULL)
	{
		printf("%d->", cur->data);
		return;
	}
	ListToheadFromLastD(cur->next);
	printf("%d->", cur->data);
}

2.从尾到头打印单链表

void ListToheadFromLast(pList* pplist)    //从尾到头打印,非递归,头插法
{
	pNode cur = NULL;
	pNode re = NULL;
	cur =(*pplist)->next;             //cur总是指向tmp的下一个节点
	(*pplist)->next = NULL;      //将第一个的节点中的指针赋为NULL,当链表的最后一个节点
	while (cur)
	{
		re = cur->next;
		cur->next = *pplist;
		*pplist = cur;
		cur = re;
	}
}

3.删除一个无头单链表的非尾节点

void EraseNotTailNode(pList* pplist,pNode pos)      //删除一个无头单链表的非尾节点
{
	assert(pos != NULL);        
	pos->data = pos->next->data;       //用下一个位置的数据把该位置的数据覆盖掉
	pNode del = pos->next;
	pos->next = del->next;
	free(del);
	del = NULL;
}

4.在无头单链表前插入一个节点

void InsertNodeNoHead(pList* pplist,pNode pos,int d)      //在一个无头单链表的一个节点前插入一个节点
{
	assert(pos != NULL);
	DataType tmp = 0;			
	pNode newNode = BuyNode(d);
	newNode->next = pos->next;								
	pos->next = newNode;
	tmp = pos->data;								//先插在指定位置的后面,再交换数值
	pos->data = newNode->data;
	newNode->data = tmp;
}

5.约瑟夫环

void JosephCricle(pList* pplist,int d)        //约瑟夫环
{
	assert(pplist != NULL);
	pNode cur = *pplist;
	pNode del = NULL;
	pNode flag = NULL;
	int i = 0;
	while (1)
	{
		i = d;
		if (cur->next == cur)
		{
			printf("幸存者:%d\n", cur->data);
			break;
		}
		while (--i)                       
		{
			flag = cur;
			cur = cur->next;
		}
		printf("杀死:%d\n", cur->data);
		del = cur;
		flag->next = del->next;
		cur = cur->next;
		free(del);
	}
}

6.冒泡排序

void BubbleSort(pList plist)     //冒泡排序
{
	assert(plist != NULL);
	pNode cur = plist;
	pNode flag = NULL;							//标记已排完序的最后一个节点
	int tmp = 0;
	while (cur!=flag)
	{
		while (cur->next!=flag)                //flag控制内层循环
		{
			if (cur->data > cur->next->data)
			{
				tmp = cur->data;
				cur->data = cur->next->data;
				cur->next->data = tmp;
			}
			cur = cur->next;
		}
		flag = cur;
		cur = plist;
	}
}

6.选择排序

void SelectSort(pList plist)            //选择排序
{
	assert(plist != NULL);
	pNode cur = plist;
	pNode tell = NULL;                   //标记最后一个节点
	pNode flag = cur;                    //标记最大元素的节点
	int tmp = 0;
	while (cur!=tell)
	{
		int max = cur->data;
		while (cur->next != tell)
		{
			if (max < cur->next->data)
			{
				max = cur->next->data;
				flag = cur->next;
			}
			cur = cur->next;
		}
		if (flag != cur)
		{
			tmp = flag->data;
			flag->data = cur->data;
			cur->data = tmp;
		}
		tell = cur;
		cur = plist;
		flag = cur;
	}
}

7.快速排序

void myQuickSort(pList pStart, pList pEnd)       //快速排序,pEnd==NULL
{
	if (pStart == NULL || pStart == pEnd)		//起始节点为空,结束
		return;
	int key = pStart->data;
	pNode cur1 = pStart;
	pNode cur2 = cur1->next;
	while (cur2 != pEnd)
	{
		if (cur2->data < key)
		{
			cur1 = cur1->next;
			myswap(&(cur1->data), &(cur2->data));
		}
		cur2 = cur2->next;
	}
	myswap(&(pStart->data), &(cur1->data));
	pNode flag = cur1;
	myQuickSort(pStart, flag);
	myQuickSort(flag->next, pEnd);
}

8.查找单链表倒数第k个节点

pNode FindFromtail(pList plist, int k)   //查找单链表倒着数第k个元素
{
	pNode cur = plist;
	pNode flag = plist;                       
	while (cur)                              //遍历链表
	{
		int d = k;
		flag = cur;                           //标记节点
		while (--d)                          //遍历k-1次
		{
			cur = cur->next;     
			if (cur == NULL)                  //一旦k大于链表的实际长度时,cur没到k-1次就会出现NULL
				return NULL;
		}
		if (cur->next == NULL)                //当遍历第k-1次后,cur的next为空,则flag就为要找的那个元素
			return flag; 
		cur = flag->next;                     //否则,从头开始下一个                             
	}
	return NULL;
}

9.合并两个有序单链表

pNode AddSort(pList* pplist1, pList* pplist2)     //合并两个有序链表,结果依然有序,递归
{
	pNode pHead = NULL;
	if (*pplist1 == NULL)
		return *pplist2;
	else if (*pplist2 == NULL)
			 return *pplist1;
	if (*pplist1 == NULL && *pplist2 == NULL)
		return NULL;
	if (((*pplist1)->data) < ((*pplist2)->data))
	{
		pHead = *pplist1;
		pHead->next = AddSort(&((*pplist1)->next), &(*pplist2));
	}
	else
	{
		pHead = *pplist2;
		pHead->next = AddSort(&(*pplist1), &((*pplist2)->next));
	}
	return pHead;
}

10.判断链表是否带环

pLinkNode CheckCycle(pList plist)           //判断链表是否带环
{
	pNode slow = plist;
	pNode fast = plist;
	while (fast && fast->next)
	{
		slow = slow->next;              //slow一次走一步
		fast = fast->next->next;        //fast一次走两步
		if (fast == slow)               //是环,总会相遇
			return fast;
	}
	return NULL;                        //不是环
}

11.求环的长度

int GetCircleLength(pLinkNode meet)      //求环的长度
{
	int len = 1;
	pNode cur = meet->next;         //meet是快慢指针的交点
	while (cur!=meet)
	{
		len++;
		cur = cur->next;
	}
	return len;
}

12.求环的入口点

pLinkNode GetCycleEntryNode(pList plist, pLinkNode meetNode)          
//求环的入口点,meetNode是带环时的快慢指针的交点
{
	pNode cur = plist;
	while (cur != meetNode)
	{
		cur = cur->next;
		meetNode = meetNode->next;
	}
	return cur;
}

13.求两个环的交点

pNode CheckCross(pList plist1, pList plist2)          //判断两个链表是否相交,若相交求交点
{
	assert(plist1 != NULL);
	assert(plist2 != NULL);
	pNode cur1 = plist1;
	pNode cur2 = plist2;
	int len1 = 1;
	int len2 = 1;
	int a = 0;
	while (cur1->next)
	{
		len1++;
		cur1 = cur1->next;
	}
	while (cur2->next)
	{
		len2++;
		cur2 = cur2->next;
	}
	if (cur1 == cur2)					 //若两个链表的尾地址相同,则相交
	{
		printf("相交\n");
		cur1 = plist1;
		cur2 = plist2;
		if (len1 < len2)                //调整,使cur1指的是长一些的链表
		{
			cur1 = plist2;
			cur2 = plist1;
		}
		a=abs(len1-len2);          //绝对值
		while (a--)
		{
			cur1 = cur1->next;      //让长的走a步,使两个链表里交点的距离相等
		}
		while (cur1 != cur2)
		{
			cur1 = cur1->next;
			cur2 = cur2->next;
		}
		printf("交点为:%d\n", cur1->data);
		return cur1;
	}
	printf("不相交\n");
	return NULL;
}

14.复杂链表的复制

思想:1.先复制节点插到每个节点的后边

           2.再复制tmp随机指针,就是原tmp指针的next

           3.最后断开成两个链表

#include "ComplexList.h"
//复杂链表的实现
pComplexNode BuyComplexNode(DataType d)   //买一个复杂节点
{
	pComplexNode newNode = (pComplexNode)malloc(sizeof(struct ComplexNode));
	if (newNode)
	{
		newNode->next = NULL;
		newNode->tmp = NULL;
		newNode->data = d;
		return newNode;
	}
	perror("the take failer:");
	return NULL;
}

void Print(pComplexList p)
{
	pComplexNode cur = p;
	if (p == NULL)
		return;
	while (cur)
	{
		printf("%d-->", cur->data);
		cur = cur->next;
	}
	printf("over\n");
}

pComplexList CopyList(pComplexList p1)                 //复制复杂链表
{
	//先复制链表插入到p1当中
	pComplexNode cur = p1;
	pComplexNode cur2 = NULL;
	pComplexNode p2 = NULL;
	pComplexNode flag = NULL;
	while (cur)
	{
		flag = cur->next;
		pComplexNode newNode = BuyComplexNode(cur->data);
		newNode->next = flag;
		cur->next = newNode;
		cur = flag;
	}
	//设置tmp
	cur = p1;
	while (cur)
	{
		if (cur->tmp != NULL)
		{
			cur->next->tmp = cur->tmp->next;
			cur = cur->next->next;
		}
		else
		{
			cur->next->tmp = NULL;
			cur = cur->next->next;
		}
	}
	//断开链表
	cur = p1;
	p2 = p1->next;
	cur2 = p2;
	while (cur->next->next)
	{
		flag = cur->next->next;
		cur->next = flag;
		cur = flag;
		cur2->next = flag->next;
		cur2 = cur2->next;
	}
	cur->next = NULL;
	return p2;
}
//销毁链表
void DestroyComplexList(pComplexList p)           //销毁链表
{
	pComplexNode del = NULL;
	while (p)
	{
		del = p->next;
		free(p);
		p = del;
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值