链表问题总结
2015-04-06 14:04
246 查看
链表问题总结
//求链表中节点的个数 unsigned int GetLenthList(ListNode * Head) { if (Head == NULL) { return 0; } unsigned int length = 0; ListNode *pCurrent = Head; while (pCurrent != NULL) { length++; pCurrent = pCurrent->m_pNext; } return length; } /* 单链表的反转 * 从头到尾遍历每一个节点,将其摘下放到新链表的最前端,注意链表为空和 * 只有一个节点的情况。时间复杂度为O(n) */ ListNode* ReverserList(ListNode* Head) { //当链表为空的时候无需反转,直接返回原链表头指针 if (Head == NULL || Head->m_pNext == NULL) { return Head; } ListNode* pReverserHead = NULL;//翻转后链表的头 ListNode* pCurrent = Head; while (pCurrent != NULL) { listNdoe* pTemp = pCurrent; pCurrent = pCurrent->m_pNext; //将当前节点插入到新链表的头 pTemp->m_pNext = pReverserHead ; pReverserHead = pTemp; } return pReverserHead; } /* 查找单链表中倒数第K个节点(K>0) * 思路是使用两个指针 第一个指针在前面走k个节点,然后第二个指针开始走。 * 这样当第一个指针走到最后一个节点的时候,那么第二指针指向的就是倒数第 * k个节点; **/ ListNode* RGetKNode(ListNode* Head, int k) { //k是从1开始的,Head为NULL 表示为空链表 if (k == 0|| Head = nullptr) { return NULL; } ListNode * First = Head; ListNdoe *Second = Head; while (First!=NULL && k-- > 1) { First = First->m_pNext; } //节点个数小于K返回 if (k>1 || First==NULL) { return NULL; } while (First->m_pNext != NULL) { First = First->m_pNext; Second = Second->m_pNext; } return Second; } /* * 查找链表的中间节点 * 思路:设置两个指针同时向前走,前面的指针一次走2步,后面的指针一次走一步, * 这样当第一个指针走到最后的时候,第二个指针正好走到中间的位置。注意链表的节点 * 个数为0和1的情况。 **/ ListNode* GetMidNode(ListNode* Head ) { if (Head == NULL || Head->m_pNext == NULL) { return NULL; } ListNode * First = Head; ListNode * Second = Head; while (First->m_pNext != NULL) { First = First->m_pNext; Second = Second->m_pNext; if (First->m_pNext != NULL) { First = First->m_pNext; } } return Second; } /* * 从尾到头打印链表 *两种思路: 使用栈,先进后出;使用递归; **/ //使用栈的方式 void RPrintList(ListNode *Head) { std::stack<ListNode *> sList; ListNdoe* pNode = pHead; while (pNode != NULL) { sList.push(pNode); pNode = pNode->next; } while (!sList.empty()) { pNode = sList.top(); printf("%d"pNode ->key); sList.pop(); } } //使用递归 void RPintList(ListNode* Head) { if (Head == NULL) { return; } else { RPintList(Head->m_pNext); printf("%d \n",Head->m_pData); } } /* * 已知链表pHead1和pHead2各自有序,把他们合并成一个链表依然有序 *注意pHead1和phead2各自为空的情况和全为空的情况。 *时间复杂度为O(max(len1 || len2)) **/ ListNode *MergedList(ListNode* pHead1, ListNode* pHead2 ) { if (pHead2 == NULL) { return pHead1; } if (pHead1 == NULL) { return pHead2; } ListNode * MergerList = NULL; ListNode * MegerListTemp = NULL; if (pHead1->m_pData < pHead2->m_pData) { MergerList = pHead1; MergerList->m_pNext = nullptr; MergerList pHead1 = pHead1->m_pNext; } else { MergerList = pHead2; MergerList->m_pNext = NULL; pHead2 = pHead2->m_pNext; } ListNode * MergedListTemp = MergerList; while (pHead1 ! = NULL && pHead2 != NULL) { if (pHead1->m_pData < pHead2->m_pData) { MergedListTemp->m_pNext = pHead1; pHead1 = pHead1->m_pNext; MergedListTemp = MegerListTemp->m_pNext; MergedListTemp->m_pNext = NULL; } else { MergedListTemp->m_pNext = pHead2; pHead2 = pHead2->m_pNext; MergedListTemp = MegerListTemp->m_pNext; MergedListTemp->m_pNext = NULL; } } if (phea1 != NULL) { MergedListTemp->m_pNext = pHead1; } else if (pHead2 != NULL) { MergedListTemp->m_pNext = pHead2 } return MergerList; } //递归算法 ListNode* MergedList(ListNode* pHead1, ListNode pHead2) { if (pHead1 == NULL) { return pHead2; } if (pHead2 == NULL) { return pHead2; } ListNode *pMergedList = NULL; if (pHead1->m_pData <pHead2.m_pData) { pMergedList = pHead1; pMergedList->m_pNext = pMergedList(pHead1->m_pNext, pHead2); } else { pMergedList = pHead2; pMergedList->m_pNext = pMergedList(pHead1, pHead2.m_pNext); } return pMergedList; } /* * 判断一个单链表中是否有环 * 用两个指针去遍历 一个pSlow 一个pFast 如果又环 则一定相遇; * 就和两个人在操场跑步一样的,如果又环则一定会相遇。 **/ bool HasCircle(ListNode* pHead) { ListNode* pSlow = pHead; ListNode* pFast = pHead; while (pFast != NULL && pFast->m_pNext != NULL) { pFast = pFast->m_pNext->m_pNext; pSlow = pSlow->m_pNext; if (pFast == pSlow) { return true; } } return false; } /* 判断两个单链表是否相交 * 如果两个链表相交,就以为这从相交的点开始,后面的元素是公用的, * 那么我们只需要判断最后一个元素是否是公用的就可以判定链表是否相交 * 如果判定他是公用的呢? 注意:用地址(指针)!用元素的时候可能会出现巧合; **/ bool IsIntersected(ListNode *pHead1, ListNode* pHead2) { if (pHead2 == NULL || pHead2 == NULL) { return false; } ListNode* pLast1 = pHead1; while (pLast1->m_pNext != NULL) { pLast1 = pLast1->m_pNext; } ListNode* pLast2 = pHead2; while (pLast2->m_pNext != NULL) { pLast2 = pLast2->m_pNext; } if (pLast2 == pLast1) { return true; } else { return false; } } /* * 给出一单链表头指针pHead和一节点指针pToBeDeleted,O(1)时间复杂度删除节点pToBeDeleted * 这是一道google面试题 如果按照一般的思路就是遍历然后删除那么时间的复杂度就是O(n) * 注意:既然人家让你这么做,那么肯定就是有解的!我们把他下一个节点的数据复制到该节点, * 然后删除下一个节点就行了!如果是最后的一个节点那么就只能遍历删除了。 * 平均的时间复杂度仍为O(1); **/ void DeleteNode(ListNode* pHead, ListNode* pToBeDeleted) { if (pToBeDeleted == NULL) { return; } if ( pToBeDeleted->m_pNext != NULL) { pToBeDeleted->m_pData = pToBeDeleted->m_pNext->m_pData; ListNode * pTemp = pToBeDeleted->m_pNext; pToBeDeleted->m_pNext = pToBeDeleted->m_pNext->m_pNext; delete pTemp; pTemp = NULL; } else { if (pHead == pToBeDeleted) //只有一个节点; { delete pToBeDeleted; pToBeDeleted = NULL; pHead = NULL; } else { ListNode* pNode = pHead; while (pNode->m_pNext != pToBeDeleted) { pNode = pNode->m_pNext; } pNode->m_pNext = NULL; delete pToBeDeleted; pToBeDeleted = NULL; } } } /* * 单链表相交的第一个节点 *可以借鉴前面判断两个但链表是否相交的做法,同时记录两个链表的长度。 *如果list1的长度为len1 ,list2的长度我len2,那么将第一节点先遍历len1-len2个长度 *这样两个节点距离想交节点的距离就相等了。 **/ ListNode* GetFirstComNode(ListNode* Head1, ListNode* Head2) { //和前面求链表是否相交相似,就是把len加上去了。 if (pHead1 == NULL || pHead2 == NULL) { return NULL; } int len1 = 1; ListNode * pTail = Head1; while (pTail->m_pNext != NULL) { pTail = pTail->m_pNext; len1++; } int len2 = 1; ListNode * pTail2 = Head2; while (pTail2->m_pNext != NULL) { pTail2 = pTail2->m_pNext; len2++; } if (pTail2 != pTail) //不相交 { return NULL } ListNode* pNode1 = Head1; ListNode* pNode2 = Head2; //是他们距离节点的距离相同 if (len1 > len2) { int k = len1 - len2; while (k--) { pNode1 = pNode1->m_pNext; } } else { int k = len2 - len1; while (k --) { pNode2 = pNode2->m_pNext; } } //判断如果相同的话就返回 while (pNode2 != pNode1) { pNode1 = pNode1->m_pNext; pNode2 = pNode2->m_pNext; } return pNode1; }
相关文章推荐
- C语言链表在笔试面试中常考问题总结
- 调试单向链表遇到问题总结
- 关于有环链表的若干问题总结
- 数据结构与算法分析笔记与总结(java实现)--链表4:单调链表合并问题
- 数据结构与算法分析笔记与总结(java实现)--链表2:倒数第k个结点问题(k从1开始)
- 链表的一些常见笔试面试问题总结及代码
- 数据结构与算法分析笔记与总结(java实现)--链表问题面试笔试注意点
- 【算法总结】LinkedList 链表问题
- 数据结构(4)--循环链表的应用之约瑟夫环问题以及线性表总结之顺序表与链表的比较
- 数据结构与算法分析笔记与总结(java实现)--链表7:含环链表找环入口结点问题
- 链表操作类型的问题总结
- 面试笔试问题总结(五)—数组、链表、二叉树
- 65. 链表是否带环、环入口、环长度、链表相交问题分析与总结
- 算法学习(六)链表问题总结,相交,成环
- 剑指offer——链表相关问题总结
- 链表问题总结
- 链表环问题总结
- 链表环问题总结
- 《剑指offer》面试题57 删除链表中重复的结点 C++ 实现 以及 错误总结 (指针问题)!!
- 数据结构与算法分析笔记与总结(java实现)--链表8:对排序链表删除重复结点问题