首页 > 代码库 > 链表学习笔记
链表学习笔记
单向链表
struct ListNode {// 单向链表 int val; struct ListNode *next; ListNode(int x) : val(x), next(NULL) {} };
从尾到头打印链表
vector<int> TravelListFromTailToHead(struct ListNode* head) {// 【从尾到头打印链表】 vector<int> result; if(NULL == head) return result; ListNode *p = head; stack<ListNode*> nodeStack; while(p != NULL) { nodeStack.push(p); p = p->next; } while(!nodeStack.empty()) { p = nodeStack.top(); result.push_back(p->val); nodeStack.pop(); } return result; }
链表中倒数第 k 个结点
ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {// 【链表中倒数第 k 个结点】 if(NULL == pListHead || 0 == k) return NULL; ListNode *p1 = pListHead, *p2 = pListHead;// 使用快慢指针 while(p2->next && k-- > 1) {// k-- > 1 一定要放在后面 p2 = p2->next; } if(k > 1) return NULL;// 说明 k 值比节点数还大 while(p2->next) { p2 = p2->next; p1 = p1->next; } return p1; }
反转链表
ListNode* ReverseList(ListNode* pHead) {// 【反转链表】 if(NULL == pHead) return NULL; ListNode *p = pHead, *pNext = pHead->next, *pPre = NULL;// 需要定义三个指针 while(pNext) { p->next = pPre; pPre = p; p = pNext; pNext = pNext->next; } p->next = pPre; return p; }
合并两个排序的链表
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {// 【合并两个排序的链表】 if(NULL == pHead1) return pHead2; if(NULL == pHead2) return pHead1; ListNode *pHead = NULL, *p;// pHead:保存新链表表头;p:用于新链表遍历生成 if(pHead1->val <= pHead2->val) { pHead = pHead1; pHead1 = pHead1->next; } else { pHead = pHead2; pHead2 = pHead2->next; } p = pHead; while(pHead1 && pHead2) { if(pHead1->val <= pHead2->val) { p->next = pHead1; pHead1 = pHead1->next; } else { p->next = pHead2; pHead2 = pHead2->next; } p = p->next; } while(pHead1) { p->next = pHead1; p = p->next; pHead1 = pHead1->next; } while(pHead2) { p->next = pHead2; p = p->next; pHead2 = pHead2->next; } return pHead; }
两个链表的第一个公共结点
ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) {// 【两个链表的第一个公共结点】 ListNode *p = pHead1, *q = pHead2; // 先计算两个链表的长度 unsigned int nLength1 = 0, nLength2 = 0; while(p != NULL && q != NULL) { nLength1++; nLength2++; p = p->next; q = q->next; } while(p != NULL) { nLength1++; p = p->next; } while(q != NULL) { nLength2++; q = q->next; } // 根据两链表的长度差,长的链表先走这个差值的步数 int n = abs(nLength1 - nLength2); p = pHead1; q = pHead2; if(nLength1 < nLength2) { p = pHead2; q = pHead1; } while(n--) p = p->next; // 对齐后,一起走,直到遇到第一个公共节点 while(p != NULL && q != NULL && p != q) { p = p->next; q = q->next; } return p; }
链表中环的入口结点
ListNode* getMeetNode(ListNode* pHead) {// 用快慢指针,必然相会于环内某个节点,返回这个节点,否则返回 NULL if(NULL == pHead) return NULL; ListNode* pSlow = pHead->next; if(NULL == pSlow) return NULL; ListNode* pFast = pSlow->next; while(pSlow != NULL && pFast != NULL) { if(pFast == pSlow) return pFast; pFast = pFast->next; pSlow = pSlow->next; if(pFast != pSlow) pFast = pFast->next; } return NULL; } ListNode* EntryNodeOfLoop(ListNode* pHead) {// 【链表中环的入口结点】 ListNode* meetNode = getMeetNode(pHead);// 用快慢指针得到环内某个节点 if(NULL == meetNode) return NULL; int n = 1; // 用这个环内节点计算得到环内节点数 ListNode* p = meetNode->next; while(p != meetNode) { p = p->next; ++n; } // 用两个指针,一个指针先走环内节点个数的步数,另一个节点在链表头 // 当两个节点相遇时,此时的节点即是环的入口节点 p = pHead; while(n--) p = p->next; ListNode* p1 = pHead; while(p1 != p) { p = p->next; p1 = p1->next; } return p; }
判断链表是否是回文结构
bool IsPalindrome(ListNode* pHead) {// 【判断链表是否是回文结构】 // 使用快慢指针,找到链表的中间 ListNode* pFast = pHead; ListNode* pSlow = pHead; while(pFast != NULL && pSlow != NULL) { pFast = pFast->next; pSlow = pSlow->next; if(pFast != NULL) pFast = pFast->next; } pSlow = ReverseList(pSlow);// 从中间节点开始将链表反转(链表被改变,即现场改变) // 从两头开始往中间遍历,判断是否是回文结构 bool flag = true; ListNode *p1 = pHead, *p2 = pSlow; while(p2 != NULL) { if(p1->val != p2->val) { flag = false; } p1 = p1->next; p2 = p2->next; } ReverseList(pSlow);// 将链表恢复(恢复现场) return flag; }
删除链表中的重复结点
删除链表中相邻的重复结点(保留一个)
void DeleteDuplication(ListNode* &pHead) {// 【删除链表中相邻的重复结点(保留一个)】 if(NULL == pHead) return; ListNode *p1 = pHead, *p2 = p1->next; while(p2 != NULL) { if(p2->val == p1->val) { while(p2 != NULL && p2->val == p1->val) { ListNode* p = p2; p2 = p2->next; delete p; p = NULL; } p1->next = p2; } if(NULL != p2) p2 = p2->next; p1 = p1->next; } }
删除链表中重复结点(保留一个)
void DeleteDuplication2(ListNode* &pHead) {// 【删除链表中重复结点(保留一个)】 if(NULL == pHead) return; set<int> s; s.insert(pHead->val); ListNode* p = pHead, *pNode = pHead->next; while(pNode != NULL) { if(s.find(pNode->val) == s.end()) { s.insert(pNode->val); p->next = pNode; p = p->next; pNode = pNode->next; } else { ListNode* q = pNode; pNode = q->next; delete q; q = NULL; p->next = NULL; } } }
删除链表中相邻重复结点
void DeleteDuplication3(ListNode* &pHead) {// 【删除链表中相邻重复结点】 if(NULL == pHead) return; ListNode *pPre = NULL, *pNode = pHead; while(pNode != NULL) { ListNode* pNext = pNode->next; if(pNext != NULL && pNext->val == pNode->val) { const int val = pNode->val; ListNode* p = pNode; while(p != NULL && val == p->val) { pNext = p->next; delete p; p = pNext; } if(NULL == pPre) pHead = pNext; else pPre->next = pNext; pNode = pNext; } else { pPre = pNode; pNode = pNode->next; } } }
复杂链表
struct RandomListNode {// 复杂链表 int val; struct RandomListNode *next, *random; RandomListNode(int x) : val(x), next(NULL), random(NULL) {} };
复杂链表的复制
RandomListNode* Clone(RandomListNode* pHead) {// 【复杂链表的复制】 if(NULL == pHead) return NULL; RandomListNode *p = pHead; while(p != NULL) { RandomListNode *pNode = new RandomListNode(p->val); pNode->next = p->next; p->next = pNode; p = pNode->next; } p = pHead; RandomListNode *pClone; while(p != NULL) { pClone = p->next; if(p->random != NULL) pClone->random = p->random->next; p = pClone->next; } p = pHead; RandomListNode *pCloneHead = pHead->next; // pClone = pHead->next; // p = pClone->next; // while(p != NULL) { // pClone->next = p->next; // pClone = pClone->next; // p->next = pClone->next; // p = p->next; // } RandomListNode *tmp; while(p->next) { tmp = p->next; p->next = tmp->next; p = tmp; } return pCloneHead; }
链表学习笔记
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。