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

来源:互联网 发布:自动数控编程软件 编辑:程序博客网 时间:2024/06/05 07:36


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

冒泡排序:

先将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. 链表不带环相交

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

2)一旦两个链表相交,那么两个链表从相交节点开始到尾节点一定都是相同的节点。

 

只有这一种情况,一共有四种解决方法

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

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

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

  4. 将链表一建立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;} 



1 0