用C++语言实现链表面试题

#include <iostream>
#include <assert.h>
#include <malloc.h>
#include <stack>
using namespace std;

typedef int DataType;
typedef struct Node
{
	DataType data;
	struct Node* next;
}Node,*pNode,*pList;

void Init(pList* head)
{
	*head = NULL;
}

void PushBack(pList* head,DataType x)//尾插
{
	Node* cur = *head;

	Node* p = (Node*)malloc(sizeof(Node));
	p->data = x;
	p->next = NULL;

	if (cur == NULL)//空链表
	{
		*head = p;
	}
	else
	{
		while (cur->next)//非空链表
		{
			cur = cur->next;
		}
		cur->next = p;
	}
}
//逆序打印链表
void PrintfromTail1(pNode head)
{
	//1.数组
	//2.逆序---->正向打印---->逆序
	//3.递归
	if (head)
	{
		PrintfromTail1(head->next);
		cout << head->data<<"--->";
	}
}

//递归转循环
void PrintfromTail2(pNode head)
{
	if (head == NULL)
		return;
	stack<Node*> s;
	Node* cur = head;
	while (cur)
	{
		s.push(cur);
		cur = cur->next;
	}
	while (!s.empty())
	{
		cur = s.top();
		cout << cur->data << " ";
		s.pop();
	}
	cout << endl;
}
void Print(pNode head)//正序打印
{
	pNode cur = head;
	for (; cur!=NULL; cur = cur->next)
	{
		cout << cur->data << " ";
	}
	cout << endl;
}

size_t size(pNode head)
{
	pNode cur = head;
	size_t count = 0;
	while (cur)
	{
		cur = cur->next;
		count++;
	}
	return count;
}
pNode Find(pNode head,size_t pos)
{
	assert(pos >= 0 && pos <= size(head));
	pNode cur = head;
	if (head == NULL)
		return NULL;
	else
	{
		for (size_t i = 0; i < pos; i++)
		{
			cur = cur->next;
		}
	}
	return cur;
}
//删除无头单链表的非尾结点
void DelteNoTail(pNode head, int pos)
{
	pNode p=Find(head, pos);
	pNode Del = p->next;
	swap(p->data, Del->data);
	p->next = Del->next;
	delete Del;
}

//在无头单链表的一个非头结点前插入一个结点
void InsertNoHead(pNode head, int pos,DataType data)
{
	pNode p = Find(head, pos);
	pNode pnext = p->next;
	pNode NewNode = new Node;
	NewNode->data = data;
	p->next = NewNode;
	NewNode->next = pnext;
	swap(p->data, NewNode->data);
}

pNode Back(pNode head)//找到最后一个元素
{
	if (head == NULL)
		return NULL;
	pNode cur = head;
	while (cur->next)
	{
		cur = cur->next;
	}
	return cur;
}
//单链表实现约瑟夫环
pNode JosephCircle(pNode head, int M)
{
	//构环
	pNode Tail = Back(head); 
	pNode cur = head;
	Tail->next = head;
	while (cur->next!=cur)
	{
		int N = M;//重要
		while (--N)//报数
		{
			cur = cur->next;
		}
		cout << cur->data<<" ";
		//替换删除
		pNode Del = cur->next;
		cur->data = Del->data;
		cur->next = Del->next;
		delete Del;
	}
	cout << endl;
	cur->next = NULL;
	head = cur;
	return cur;
}

//逆置/反转单链表
//1.三个指针
pNode Reverse(pNode& head)
{
	//空链表,只有一个结点的链表
	if (head==NULL || head->next==NULL)
		return head;

	pNode pPre = NULL;
	pNode pCur = head;
	pNode pNext = head->next;

	while (pNext)
	{
		pCur->next = pPre;
		pPre = pCur;
		pCur = pNext;
		pNext = pCur->next;
	}
	pCur->next = pPre;
	head = pCur;
}

//头插逆置
pNode ReverList(pNode& head)
{
	pNode pCur = head;
	pNode pCurNext = NULL;
	pNode Newhead = NULL;
	while (pCur)
	{
		pCurNext = pCur->next;
		pCur->next = Newhead;
		Newhead = pCur;
		pCur = pCurNext;
	}
	return Newhead;
}

//单链表排序
void BubbleSort(pNode head)
{
	if (head == NULL || head->next == NULL)
		return;
	
	pNode pCur = head;
	pNode pNext = pCur->next;
	pNode pTail = NULL;
	bool ischange = false;
	while (pTail != head)
	{
		pCur = head;
		pNext = pNext->next;
		ischange = false;//标志,检查是否发生交换
		while (pNext)
		{
			if (pCur->data > pNext->data)
			{
				swap(pCur->data, pNext->data);
				ischange = true;
			}
			pCur = pNext;
			pNext = pNext->next;
		}
		pTail = pCur;
		if (!ischange)//没有交换
			return;
	}
}

//合并两个有序链表,合并后仍有序
pNode Merge2List(pNode phead1, pNode phead2)
{
	pNode L1 = phead1;
	pNode L2 = phead2;
	pNode pNewNode = NULL;
	pNode pTail = NULL;
	
	//有一个为空
	if (L1 == NULL)
		return L2;
	if (L2 == NULL)
		return L1;

	//设置第一个头指针的位置在head1还是head2的位置
	if (L1->data <= L2->data)
	{
		pNewNode = L1;
		pTail = pNewNode;
		L1 = L1->next;
	}
	else
	{
		pNewNode = L2;
		pTail = pNewNode;
		L2 = L2->next;
	}

	//比较,每次比较小的尾插在新链表中
	while (L1&&L2)
	{
		if (L1->data <= L2->data)
		{
			pTail->next = L1;
			L1 = L1->next;
		}
		else
		{
			pTail->next = L2;
			L2 = L2->next;
		}
		pTail = pTail->next;
	}

	//一个链表走到尾,另一个链表直接连接在新链表的尾部
	if (L1)
		pTail->next = L1;
	if (L2)
		pTail->next = L2;

	return pNewNode;
}

//查找中间结点
pNode MidNode(pNode head)
{
	pNode fast = head;
	pNode slow = head;
	pNode cur = head;

	if (head == NULL||head->next==NULL)
		return head;
	//while (fast)
	//{
	//	fast = fast->next->next;
	//	slow = slow->next;
	//}
	//return slow;//偶数返回中间的后一个

	while (fast->next&&fast->next->next)
	{
		fast = fast->next->next;
		slow = slow->next;
	}
	return slow;
}

//删除倒数第k个结点
void DelRekNode(pNode head, size_t k)
{
	pNode fast = head;
	pNode slow = head;
	pNode cur = NULL;
	pNode Del = NULL;

	if (NULL == head || k == 0)//链表为空或k为0
		return;
	while (k--)//快指针先走k步
	{
		fast = fast->next;
	}
	while (fast->next)
	{
		fast = fast->next;
		slow = slow->next;
	}
	cur = slow;//cur指向要删除结点的前一个结点
	Del = cur->next;
	cur->next = Del->next;
	delete Del;
}
/*
//判断链表是否带环
bool IsCricle(pNode head)
{
	pNode fast = head;
	pNode slow = head;

	while (fast&&slow)
	{
		if (fast == slow)
			return true;
		else
			return false;
		fast = fast->next->next;
		slow = slow->next;
	}

}
*/
//判断是否带环,返回两个指针相遇位置
pNode IsCricle(pNode head)
{
	pNode fast = head;
	pNode slow = head;

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

//求环的长度
size_t LenofCricleList(pNode head)
{
	pNode meet = IsCricle(head);
	assert(meet);
	int count = 1;
	pNode cur =meet;

	while (cur->next!=meet)
	{
		cur = cur->next;
		count++;
	}
	return count;
}

//求环入口地址
pNode ExtofCircle(pNode head)
{
	pNode meet = IsCricle(head);
	assert(meet);
	pNode cur = head;

	while (cur!=meet)
	{
		meet = meet->next;
		cur = cur->next;
	}
	return cur;
}

size_t LenNoCircle(pNode head)
{
	size_t len = 0;
	while (head)
	{
		head = head->next;
		len++;
	}
	return len;
}

//判断两链表是否相交,若相交,求交点
pNode CheckCross(pNode head1, pNode head2)
{
	pNode cur1 = head1;
	pNode cur2 = head2;
	//两个链表均不带环
	if ((!IsCricle(head1)) && (!IsCricle(head2)))
	{
		size_t len1 = LenNoCircle(head1);
		size_t len2 = LenNoCircle(head2);
		if (len1 > len2)
		{
			//头指针为head1的链表先走len2-len1步
			for (int i = 0; i < len2 - len1; i++)
			{
				cur1 = cur1->next;
			}
		}
		if (len1>len2)
		{
			for (size_t i = 0; i <= len1 - len2; i++)
			{
				cur2 = cur2->next;
			}
		}
		//两个指针一起走
		while ((NULL != cur1) && (NULL != cur2))
		{
			cur1 = cur1->next;
			cur2 = cur2->next;
			if (cur1 == cur2)
				return cur1;
		}
	}
	//两个链表均带环
	else if (IsCricle(head1) && IsCricle(head2))
	{
		//交点在环外
		pNode ex1 = ExtofCircle(head1);
		pNode ex2 = ExtofCircle(head2);
		if (ex1 == ex2)
		{
			//两个链表环外的部分的长度
			ex1->next = NULL;
			ex2->next = NULL;
			size_t len1 = LenNoCircle(head1);
			size_t len2 = LenNoCircle(head2);
			while (len1 < len2)
			{
				for (size_t i = 0; i < len1 - len2; i++)
				{
					cur2 = cur2->next;
				}
			}
			while (len1>len2)
			{
				for (size_t i = 0; i < len2 - len1; i++)
				{
					cur1 = cur1->next;
				}
			}
			while (NULL != cur1&&NULL != cur2)
			{
				cur1 = cur1->next;
				cur2 = cur2->next;
				if (cur1 == cur2)
					return cur1;
			}
		}
		else
		{
			return ex1;
		}
	}
	//其他情况
	return NULL;
}


int main()
{
	Node* head0 = NULL;//不带环
	Init(&head0);
	PushBack(&head0, 1);
	PushBack(&head0, 4);
	PushBack(&head0, 6);
	PushBack(&head0, 8);
	pNode tail = Back(head0);

	Node* head1 = NULL;//不带环
	Init(&head1);
	PushBack(&head1, 1);
	PushBack(&head1, 3);
	pNode mid = Back(head1);
	PushBack(&head1, 5);
	PushBack(&head1, 7);
	

	tail->next = mid;
	pNode p=CheckCross(head0, head1);
	cout << p << endl;

	Node* head2 = NULL;//带环
	Init(&head2);
	PushBack(&head2, 2);
	PushBack(&head2, 3);
	PushBack(&head2, 7);
	PushBack(&head2, 9);
	pNode pTail = Back(head2);
	pTail->next = head2;
	//Print(head);

	//DelteNTail(head, 1);
	//Print(head);

	//InsertNoHead(head, 2,10);
	//Print(head);

	//JosephCircle(head, 2);

	//Reverse(head);
	//Print(head);

	//pNode p =ReverList(head);
	//Print(p);

	//BubbleSort(head);
	//Print(head);

	//pNode p=Merge2List(head, head1);
	//Print(p);
	
	//pNode mid = MidNode(head);
	//cout << mid->data << endl;

	//DelRekNode(head, 3);
	//Print(head);

	//if (IsCricle(head1))
		//cout << "1" << endl;
	//else
		//cout << "-1" << endl;

	//int len = LenofCricleList(head1);
	//cout << len << endl;

	//ExtofCircle(head1);

	system("pause:");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值