您的位置:首页 > 职场人生

热门题---链表面试题总结

2016-06-24 00:34 375 查看

单链表一直是面试中的重点,今天就把常见的单链表面试题总结了一下

冒泡排序:

先将tail置为空,让prev和cur不停的往前走,条件cur不等于tail 控制每一趟冒泡,找出每次的最大值,再用prev不等于tail控制每一层冒泡,每趟交换完成后将prev的值给tail,让tail 不停的往前走,

代码实现

void Bubble(pLinkList list)
{
pLinkNode cur = NULL;
pLinkNode prev = NULL;
pLinkNode tail = NULL;
int exage = 0;
assert(list);
cur = list->pHead;
if (list->pHead == NULL)
{
return;
}
while (list->pHead != tail)
{
prev = list->pHead;
cur = prev->next;
while (cur != tail)
{
exage = 0;
if (cur->data < prev->data)
{
DataType x = cur->data;
cur->data = prev->data;
prev->data = x;
exage = 1;
}
prev = cur;
cur = cur->next;
}
tail = prev;
if (exage == 0)
{
return;
}
}
}

合并两个有序链表,合并后链表依然有序,

比较两条链表的第一个节点的大小,让新链表的头指向比较后的结果,如上图中指向第二条链表的第一个节点,则让指向cur2往后走,再与cur1进行比较,newhead的next指向下一个比较后的结果

代码实现

pLinkNode MerageSortList(pLinkList p1, pLinkList p2)//合并两个有序链表
{
assert(p1);
assert(p2);
if (p1->pHead == NULL)
return p2->pHead;
if (p2->pHead == NULL)
return p1->pHead;

pLinkNode cur1 = p1->pHead;
pLinkNode cur2 = p2->pHead;
pLinkNode newHead = cur1->data < cur2->data ? p1->pHead:p2->pHead;

pLinkNode Tail = newHead;

while (cur1&&cur2)
{
if (cur1->data > cur2->data)
{
Tail ->next = cur1;
cur1 = cur1->next;
}
else
{
Tail ->next = cur2;
cur2 = cur2->next;
}
Tail = Tail->next;

Tail->next = NULL;
}

if (cur1)
{
Tail->next = cur1;
}
if (cur2)
{
Tail->next = cur2;
}
return newHead;
}

约瑟夫环的问题

代码实现

pLinkNode JosePhCycle(pLinkList p, size_t m)//约瑟夫环
{
pLinkNode cur = p->pHead;
assert(p);

while (1)
{
if (cur == NULL)
return NULL;
else if (cur == cur->next)//只剩一个节点了
return cur;
else
{
int x = m;

while (--x)
{
cur = cur->next;
}
pLinkNode del = cur->next;
cur->data = del->data;
cur->next = del->next;
free(del);
del = NULL;

}

}

}

链表相交问题:

链表不带环相交

(1)一旦两个链表相交,那么两个链表中的节点一定有相同地址。

(2)一旦两个链表相交,那么两个链表从相交节点开始到尾节点一定都是相同的节点。
 
只有这一种情况,一共有四种解决方法

直接将两个链表中的节点进行比较,如果节点相同就说明链表相交,如果直到其中一个链表遍历完都没有找到相同节点,说明链表不相交。但效率很低

如果两个链表相交,则链表最后一个节点肯定相同,则只需判断链表的最后一个节点是否相同,相同则说明两链表相交

将链表一的尾节点指针指向链表二的头节点,判断链表是否有环,如果链表有环则两链表相交,如果链表无环,则证明两链表不相交,优化想法:因为链表二的头节点肯定在环中,所以可以直接从链表二的头节点开始判断

将链表一建立hash表,用链表二中的节点在hash表中进行查询,看是否有相同节点,缺点:增加了内存消耗

代码实现

pLinkNode IslistCricle1(pLinkList plist1, pLinkList plist2)
{
assert(plist1);
assert(plist2);
pLinkNode cur1 = plist1->pHead;
pLinkNode cur2 = plist2->pHead;
if (plist1->pHead == NULL)
{
printf("链表不相交\n");
return NULL;
}
if (plist2->pHead == NULL)
{
printf("链表不相交\n");
return NULL;
}

while (cur1 && cur2)
{
cur1 = plist1->pHead;
while (cur1&&cur2)
{
if (cur1 == cur2)
{
printf("链表相交于%d结点\n", cur1->data);
return cur1;
}
cur1 = cur1->next;
//cur2 = cur2->next;
}
cur2 = cur2->next;
}

return NULL;
}

void IslistCricle2(pLinkList plist1, pLinkList plist2)
{
assert(plist1);
assert(plist2);
pLinkNode cur1 = plist1->pHead;
pLinkNode cur2 = plist2->pHead;

if (plist1->pHead == NULL)
{
printf("链表不相交\n");
return;
}
if (plist2->pHead == NULL)
{
printf("链表不相交\n");
return;
}

while (cur1->next)
{
cur1 = cur1->next;
}
while (cur2->next)
{
cur2 = cur2->next;
}

if (cur1 == cur2)
{
printf("链表相交\n");
}
return;
}

pLinkNode IslistCricle3(pLinkList plist1, pLinkList plist2)
{
assert(plist1);
assert(plist2);
pLinkNode cur1 = plist1->pHead;
pLinkNode cur2 = plist2->pHead;

if (plist1->pHead == NULL)
{
printf("链表不相交\n");
return NULL;
}
if (plist2->pHead == NULL)
{
printf("链表不相交\n");
return NULL;
}
while (cur2->next)
{
cur2 = cur2->next;
}
cur2->next = cur1;
cur2 = plist2->pHead;
cur1 = plist1->pHead;
while (cur2&&cur2->next)
{
cur1 = cur1->next;
cur2 = cur2->next->next;
if (cur1 == cur2)
{
printf("链表相交\n");
return cur1;
}
}

}

复杂链表的拷贝

代码实现

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

typedef int  Datatype;

typedef struct Complex
{
Datatype data;
Complex* next;
Complex* redom;
}Complex, *pComplex;

pComplex BuyNode(Datatype x)
{
pComplex tmp = (pComplex)malloc(sizeof(Complex));
if (tmp)
{
tmp->data = x;
tmp->next = NULL;
tmp->redom = NULL;
}
return tmp;
}

void Printf(pComplex head)
{
while (head)
{
printf("head:%d,redom->%d\n", head->data, head->redom->data);
head = head->next;
}
}

pComplex CopyComplexLinkList(pComplex head)
{
pComplex newhead = head;
pComplex tail = head;
pComplex cur = head;

while (cur)
{
pComplex tmp = BuyNode(cur->data);
tmp->next = cur->next;
cur->next = tmp;
cur = cur->next->next;
}
cur = head;
while (cur)
{
cur->next->redom = cur->redom;
cur = cur->next->next;
}

cur = head;
newhead = cur->next;
while (cur && cur->next)
{
tail = cur->next;
tail = tail->next;
cur->next = cur->next->next;
cur = cur->next;
}
return newhead;
}

void Test()
{
pComplex c1 = BuyNode(1);
pComplex c2 = BuyNode(2);
pComplex c3 = BuyNode(3);
pComplex c4 = BuyNode(4);
pComplex c5 = BuyNode(5);

c1->next = c2;
c2->next = c3;
c3->next = c4;
c4->next = c5;

c1->redom = c3;
c2->redom = c4;
c3->redom = c5;
c4->redom = c1;
c5->redom = c2;

c1 = CopyComplexLinkList(c1);

Printf(c1);

}
int main()
{
Test();
system("pause");
return 0;
}

下面是用c++的引用实现的一份功能相同的代码

代码实现

//冒泡排序
void Bubble(SListNode* pHead)
{
int exange = 0;
if (pHead == NULL || pHead->next == NULL)
{
return;
}
SListNode* prev = pHead;
SListNode* cur = pHead->next;
SListNode* Tail = NULL;
while (Tail != pHead)
{
cur = pHead->next;
prev = pHead;
while (cur != Tail)
{
if (prev->data > cur->data)
{
DataType x;
x = cur->data;
cur->data = prev->data;
prev->data = x;
}
prev = cur;
cur = cur->next;
}
Tail = prev;
}
}

//删除一个无头单链表的非尾节点
void DelNonTailNode(SListNode* pos)
{
assert(pos);
assert(pos->next);

SListNode* del = pos->next;
pos->data = del->data;
pos->next = del->next;
free(del);
del = NULL;
}

//在无头单链表的非头节点插入一个节点
void InsertNonTailNode(SListNode* pos,DataType x)
{
assert(pos);
SListNode* cur = Buynode(pos->data);
SListNode* temp = pos->next;
cur->next = temp;
pos->next = cur;
pos->data = x;
}

//查找单链表的中间节点并只能遍历一次链表(快慢指针)

SListNode* FindMidNode(SListNode* pHead)
{
assert(pHead);

if (pHead->next == NULL)
{
return pHead;
}
else
{
SListNode* slow = pHead;
SListNode* fast = pHead;
/* while (fast)
{
if (fast->next)
{
fast = fast->next->next;
}
else
{
break;
}
slow = slow->next;
}*/
while (fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}
return NULL;
}

//查找链表的倒数第k个节点,且只能遍历链表一次

SListNode* FindNode(SListNode* pHead, int k)
{
assert(pHead);
assert(k >= 0);

SListNode* slow = pHead;
SListNode* fast = pHead;
//有问题
/*while (fast && fast->next)
{
while (k--)
{
fast = fast->next;
}
fast = fast->next;
slow = slow->next;
}*/
while (fast && --k)
{
fast = fast->next;
if (fast == NULL)
{
return NULL;
}
}

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

//从尾到头打印单链表

void PrintTailToHead(SListNode* pHead)
{
if (pHead == NULL)
{
return;
}
else
{
PrintTailToHead(pHead->next);
printf("%d ", pHead->data);
}
}

//逆置单链表 很重要
SListNode* Reverse(SListNode* pHead)
{
SListNode* cur = pHead;
SListNode* newHead = NULL;

while (cur)
{
SListNode* temp = cur;
cur = cur->next;

temp->next = newHead;
newHead = temp;
}
return newHead;
}

//单链表实现约瑟夫环
//运行时先构造环,注意在代码结尾解环

SListNode* JosePhCycle(SListNode* pHead, int m)
{
SListNode* cur = pHead;
while (1)
{
if (cur == NULL)
{
return NULL;
}
else if (cur == cur->next)//只剩一个节点
{
return cur;
}
else
{
int x = m;
while (--x)
{
cur = cur->next;
}
SListNode* del = cur->next;
cur->data = del->data;
cur->next = del->next;
free(del);
del = NULL;
}
}

}

//合并两个有序链表,合并后依然有序

SListNode* Meragelist(SListNode* pHead1, SListNode* pHead2)
{
if (pHead1 == NULL)
{
return pHead2;
}
if (pHead2 == NULL)
{
return pHead1;
}
/*SListNode* newHead = pHead1->data < pHead2->data ? pHead1:pHead2;

while (pHead1 == NULL || pHead2 == NULL)
{
if (pHead1->data < pHead2->data)
{
newHead = pHead1;
pHead1 = pHead1->next;
}
else if (pHead1->data == pHead2->data)
{
newHead = pHead1;
newHead->next = pHead2;
pHead1 = pHead1->next;
pHead2 = pHead2->next;
}
else
{
newHead = pHead2;
pHead2 = pHead2->next;
}
newHead = newHead->next;
newHead->next = NULL;
}
while (pHead1)
{
newHead->next = pHead1;
pHead1 = pHead1->next;
}
while (pHead2)*/

SListNode* newHead = NULL;
SListNode* cur1 = pHead1;
SListNode* cur2 = pHead2;
if (cur1->data < cur2->data)
{
newHead = cur1;
cur1 = cur1->next;
}
SListNode* Tail = newHead;
while (cur1 && cur2)
{
if (cur1->data < cur2->data)
{
Tail->next = cur1;
cur1 = cur1->next;
}
else
{
Tail->next = cur2;
cur2 = cur2->next;
}
Tail = Tail->next;
Tail->next = NULL;
}
if (cur1 != NULL)
{
Tail->next = cur1;
}
if (cur2 != NULL)
{
Tail->next = cur2;
}
return newHead;
}

//判断链表是否带环(可以用快慢指针解决)
bool IsSListCycle(SListNode* pHead)
{
if (pHead == NULL)
{
printf("The SList is empty\n");
return false;
}
SListNode* slow = pHead;
SListNode* fast = pHead;

while (fast && fast->next)
{
fast = fast->next->next;
slow = slow->next;
if (fast == slow)
{
SListNode* cur = slow;
int length = 0; //环的长度
do
{
slow = slow->next;
length++;

} while (cur != slow);

printf("%d\n", length);
printf("The SList have cycle\n");
return true;
}
}
printf("The SList NO cycle\n");
return false;
}

//环的入口点

SListNode* CycleEntry(SListNode* pHead)
{
if (pHead == NULL)
{
printf("The SList is empty\n");
return NULL;
}
SListNode* slow = pHead;
SListNode* fast = pHead;

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

//链表是否相交,若相交,求交点(不带环)

SListNode* IsItersect(SListNode* pHead1,SListNode* pHead2)
{
if (pHead1 == NULL)
{
printf("链表不相交\n");
return pHead2;
}
if (pHead2 == NULL)
{
printf("链表不相交\n");
return pHead1;
}
SListNode* cur1 = pHead1;
SListNode* cur2 = pHead2;

while (cur1 && cur2)
{
if (cur1 == cur2)
{
printf("链表相交,交点为:%d\n", cur1->data);
return cur1;
}
cur1 = cur1->next;
cur2 = cur2 ->next;
}
return NULL;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: