链表题目总结
题目.单链表的反序
- node* reverse(node *head)
- {
- if(head == NULL || head->next == NULL)
- {
- return head;
- }
- node *cur = head;
- node *pre = NULL;
- node *tmp;
- while(cur->next)
- {
- tmp = pre;
- pre = cur;
- cur = cur->next;
- pre->next = tmp; //操作pre的next逆转
- }
- cur->next = pre; //结束时,操作cur的next逆转
- return cur;
- }
题目.给单链表建环
//给单链表建环,让尾指针,指向第num个节点,若没有,返回false
- bool bulid_looplink(node *head, int num)
- {
- node *cur = head;
- node *tail = NULL;
- int i = 0;
- if(num <= 0 || head == NULL)
- {
- return false;
- }
- for(i = 1; i < num; ++i)
- {
- if(cur == NULL)
- {
- return false;
- }
- cur = cur->next;
- }
- tail = cur;
- while(tail->next)
- {
- tail = tail->next;
- }
- tail->next = cur;
- return true;
- }
题目.检测单链表是否有环
- bool detect_looplink(node *head)
- {
- node *quick_node = head->next, *slow_node = head;
- if(head == NULL || head->next == NULL)
- {
- return false;
- }
- while(quick_node != slow_node)
- {
- if(quick_node == NULL || slow_node == NULL)
- break;
- quick_node = quick_node->next->next;
- slow_node = slow_node->next;
- }
- if(quick_node != NULL && slow_node != NULL) //非尾节点相遇
- return true;
- return false;
- }
题目.给单链表解环
ps:为了增加节点位图的效率,本应使用hash或则红黑树,这里不造车了,直接用 set容器
- //思路:先找到环节点:被2个节点指向的节点(一定有环的条件)ps:不考虑中间环,因为只有一个next节点,只可能是尾环
- bool unloop_link(node *head)
- {
- set<node *> node_bitmap; //node的地址位图
- unsigned int num = 0;
- node *cur = head, *pre = NULL;
- while(cur != NULL)
- {
- if(!node_bitmap.count(cur) ) //该节点未被遍历过
- {
- node_bitmap.insert(cur);
- ++num;
- }
- else //指向已被遍历过的节点,此时pre节点为尾节点
- {
- pre->next = NULL;
- return true;
- }
- pre = cur;
- cur = cur->next;
- }
- return false;
- }
题目.检测两条链表是否相交
- //思路:把2个链表各遍历一遍,记下长度length1和length2,若2者的尾节点指针相等,则相交。
- // 之后再把长的链表从abs(len1-len2)的位置开始遍历,第一个相等的指针为目标节点
- node* detect_intersect_links(node *first_link, node *second_link)
- {
- int legnth1 = 1, length2 = 1, pos = 0;
- node *cur = NULL, *longer_link = first_link, *shorter_link = second_link;
- if(first_link == NULL || second_link == NULL)
- {
- return NULL;
- }
- while(first_link->next || second_link->next) //遍历2个链表
- {
- if(first_link->next)
- {
- first_link = first_link->next;
- ++legnth1;
- }
- if(second_link->next)
- {
- second_link = second_link->next;
- ++length2;
- }
- }
- if(first_link != second_link) //比较尾节点
- {
- return NULL;
- }
- pos = legnth1 - length2;
- if(legnth1 < length2) //保证 longer_link为长链表
- {
- pos = length2 - legnth1;
- cur = longer_link;
- longer_link = shorter_link;
- shorter_link = cur;
- }
- while(pos-- > 0)
- longer_link = longer_link->next;
- while(longer_link || shorter_link)
- {
- if(longer_link == shorter_link) //找到第一个交点
- {
- return longer_link;
- }
- longer_link = longer_link->next;
- shorter_link = shorter_link->next;
- }
- return NULL;
- }
题目.不输入头节点,删除单链表的指定节点(只给定待删除节点指针)
- //思路:由于没有头节点,非循环单链表,无法获取目标节点的前节点,所以只能把它的next节点数据前移,并删除next节点
- //ps:当传入节点为尾节点,无法用此方法删除
- bool withouthead_delete_node(node *target_node)
- {
- node *cur = NULL;
- if(target_node == NULL || target_node->next == NULL) //空节点或者尾节点,失败
- {
- return false;
- }
- cur = target_node->next;
- target_node->name = cur->name;
- target_node->next = cur->next;
- delete cur;
- return true;
- }
题目: 1.判断2个链表是否相交 2.判断一个链表内部是否有循环
第一步:
用3个指针应该可以判断相交,P1、P3指向链表A,P1每次+1 P3每次+2,如果P3跑到尾了,则P1 = P3,让P1在尾巴等着(情况1)
如果P1与P3相遇了,则说明有环路,P1停下在相遇点等着(情况2)
P2和P3指向链表B,P2每次+1 P3每次+2,如果P3跑到尾了,如果第一步属于情况1,则判断是否P3 = P1,如果相等,说明A与B相交
如果第一步属于情况2,则A与B不相交。
如果P2和P3相遇了,则说明B中也有环路。让P2在相遇点停下,P1开始跑,每步+1,P3开始跑,每步+2,
如果P3与P2再次相遇前没有与P1相遇,且P1与P2也未相遇,则A与B不相交,否则相交。
说的有点乱,整理一下,用3个指针应该可以判断相交
第一步:
P1、P3指向链表A,P1每次+1 P3每次+2
情况1-1:如果P3跑到尾了,则P1 = P3,让P1在尾巴等着。
情况1-2:如果P1与P3相遇了,则说明有环路,P1停下在相遇点等着。
第二步:
P2和P3指向链表B,P2每次+1 P3每次+2
情况2-1:如果P3跑到尾了。
如果情况1-1,则判断是否P3 = P1,如果相等,说明A与B相交,否则不相交。
如果情况1-2,则A与B不相交。
情况2-2:如果P2和P3相遇了,则说明B中也有环路。让P2在相遇点停下。
如果情况1-1,则A与B不相交。
如果情况1-2,P1开始跑,每步+1,P3继续跑,每步+2,
如果P3与P2再次相遇前没有与P1相遇,且P1与P2也未相遇,则A与B不相交,否则相交。