数据结构之链表编程(C++)
来源:互联网 发布:马蓉面相 知乎 编辑:程序博客网 时间:2024/05/01 07:22
本例中单链表未添加头结点。
结点定义为:
struct ListNode{ int data; ListNode* next; ListNode(int x) :data(x), next(nullptr) {}};
1 单链表尾部添加结点
void AddToTail(ListNode** pHead, int value){ ListNode* pNew = new ListNode(value); if (*pHead == nullptr) *pHead = pNew; else { ListNode* pNode = *pHead; while (pNode->next != nullptr) pNode = pNode->next; pNode->next = pNew; }}
2 删除第i个结点,认为链表非空。
bool DeleteNode(ListNode** pHead, int n){ if (n == 1) { *pHead = (*pHead)->next; return true; } ListNode* pNode = *pHead; int j = 1; while (pNode->next && j < n-1) { pNode = pNode->next; j++; } if (!(pNode->next) || j != n-1) return false; ListNode* pDelete = pNode->next; pNode->next = pDelete->next; delete pDelete; pDelete = nullptr; return true;}
3 第i个位置前插入结点
bool InSertList(ListNode** pHead, int pos, int value){ ListNode* pNew = new ListNode(value); if (pos == 1) { pNew->next = *pHead; *pHead = pNew; return true; } int j = 1; ListNode* pNode = *pHead; while (pNode && j<pos-1) { pNode = pNode->next; j++; } if (!pNode || j!=pos-1) return false; ListNode* pNext = pNode->next; pNode->next = pNew; pNew->next = pNext; return true;}
4 从尾到头打印链表,通常打印是只读操作。方法一利用栈实现,未修改链表结构。
void PrintListReverse(ListNode* pHead){ stack<int> nodes; ListNode* pNode = pHead; while (pNode) { nodes.push(pNode->data); pNode = pNode->next; } while (!nodes.empty()) { cout << nodes.top() << ' '; nodes.pop(); }}
方法二反转链表,改变了链表结构。打印部分略去。
ListNode* ReverseList(ListNode* pHead){ ListNode* pReverseHead = nullptr; //建立返回值,简化输入 ListNode* pPrev = nullptr; ListNode* pNode = pHead; while (pNode) { ListNode* pNext = pNode->next; if (!pNext) pReverseHead = pNode; //不立即返回的原因是还要再连接pNode与pPrev pNode->next = pPrev; pPrev = pNode; pNode = pNext; } return pReverseHead;}
5 给定单链表头指针和一个结点(待删除的)指针,o(1)时间内删除该结点
将结点后一位的值赋给前一位,再将后一位删除。要注意的情况有删除的结点是否为尾结点;
链表中是否只有一个结点;并默认待删除的结点位于链表之内。
void DeleteNode(ListNode** pHead, ListNode* pToDelete){ if (!pHead || !pToDelete) return; if (pToDelete->next) //不是尾结点 { ListNode* pNext = pToDelete->next; pToDelete->data = pNext->data; pToDelete->next = pNext->next; delete pNext; pNext = nullptr; } else if (*pHead == pToDelete) //只有一个结点 { delete pToDelete; pToDelete = nullptr; *pHead = nullptr; } else //是尾结点 { ListNode* pNode = *pHead; while (pNode->next != pToDelete) pNode = pNode->next; delete pToDelete; pToDelete = nullptr; pNode->next = nullptr; }}
6 输入一个链表,输出链表的倒数第k个结点, 从1开始计数。
单链表使用两个指针可以在遍历一遍的情况下,完成任务。
ListNode* FindLastK(ListNode* pHead, int k){ if (!pHead || k < 1) return nullptr; ListNode* pAhead = nullptr; ListNode* pBehind = pHead; for (int i=0;i<k-1;++i) { pBehind = pBehind->next; if (!pBehind) return nullptr; } pAhead = pHead; while (pBehind->next) { pAhead = pAhead->next; pBehind = pBehind->next; } return pAhead;}
7 合并两个排序的链表
输入两个递增排序的链表,合并两个链表使结点仍是递增排序的。举例1–3-5-7,2-4-6-8
1-2-3-4-5-6-7-8. 相同重复的问题考虑递归调用。
ListNode* Merge(ListNode* pHead1, ListNode* pHead2){ if (!pHead1) return pHead2; else if (!pHead2) return pHead1; ListNode* pHeadMerge = nullptr; if (pHead1->data > pHead2->data) { pHeadMerge = pHead2; pHeadMerge->next = Merge(pHead1, pHead2->next); } else { pHeadMerge = pHead1; pHeadMerge->next = Merge(pHead1->next, pHead2); } return pHeadMerge;}
8 复杂链表的复制。每个结点除了有一个next指针指向下一个结点,还有一个pBling指向链表的任意结点。大问题化分成一个个的小问题。找到影响效率的关键,再找效率高的替代解决方案。
结点定义为:
struct complexListNode{ int data; complexListNode* next; complexListNode* bling; complexListNode(int x) :data(x), next(nullptr), bling(nullptr) {};};
实现的有三部分,1 本来是A-B-C-D, 变为A-A’-B-B’-C-C’-D-D’;
void CloneNodes(complexListNode* pHead){ complexListNode* pNode = pHead; while (pNode) { complexListNode* pNew = new complexListNode(pNode->data); pNew->next = pNode->next; pNode->next = pNew; pNode = pNew->next; }}
2 将原有的A-B-C-D的bling的下一位赋给A’-B’-C’-D’.
void connectPBling(complexListNode* pHead){ complexListNode* pNode = pHead; while (pNode) { complexListNode* pNodeClone = pNode->next; if (pNode->bling) pNodeClone->bling = pNode->bling->next; pNode = pNodeClone->next; }}
3 拆分两个链表为 A-B-C-D和A’-B’-C’-D’
complexListNode* seperate(complexListNode* pHead){ complexListNode* pNode = pHead; complexListNode* pHeadClone = pNode->next; complexListNode* pNodeClone = pNode->next; while (pNode) { pNode->next = pNodeClone->next; pNode = pNode->next; if (!pNode) //pNode到达尾部 break; pNodeClone->next = pNode->next; pNodeClone = pNodeClone->next; } return pHeadClone;}
4 合起来为:
complexListNode* clone(complexListNode* pHead){ if (!pHead) return nullptr; CloneNodes(pHead); connectPBling(pHead); return seperate(pHead);}
9 输入两个链表,找出它们的第一个公共结点。
ListNode* FindCommonNode(ListNode* pHead1, ListNode* pHead2){ if (!pHead1 || !pHead2) return nullptr; int length1 = 0, length2 = 0; ListNode* pNode = pHead1; while (pNode) { pNode = pNode->next; length1++; } pNode = pHead2; while (pNode) { pNode = pNode->next; length2++; } int lenghtdif = length1 - length2; ListNode* pHeadLong = pHead1; ListNode* pHeadShort = pHead2; if (length1 < length2) { pHeadLong = pHead2; pHeadShort = pHead1; lenghtdif = length2 - length1; } for (int i = 0; i < lenghtdif; ++i) pHeadLong = pHeadLong->next; while (pHeadLong && pHeadShort && pHeadLong!=pHeadShort) { pHeadLong = pHeadLong->next; pHeadShort = pHeadShort->next; } return pHeadLong;}
10 输入一颗二叉搜索树,将该二叉搜索树转换成排序的双向链表。只能调整树中结点指针的方向。
递归的一个重要思想,子问题已完成。大问题分解成小问题。
struct BinaryTreeNode{ int data; BinaryTreeNode* left; BinaryTreeNode* right;};BinaryTreeNode* Convert(BinaryTreeNode* pRoot){ BinaryTreeNode* pLastNode = nullptr; ConvertNode(pRoot, &pLastNode); BinaryTreeNode* pHead = pLastNode; while (pHead && pHead->left) pHead = pHead->left; return pHead;}void ConvertNode(BinaryTreeNode* pRoot, BinaryTreeNode** pLastNode){ if (!pRoot) return; BinaryTreeNode* pCurrent = pRoot; if (pCurrent->left) ConvertNode(pRoot->left, pLastNode); pCurrent->left = *pLastNode; if (*pLastNode) (*pLastNode)->right = pCurrent; *pLastNode = pCurrent; if (pCurrent->right) ConvertNode(pRoot->right, pLastNode);}
11 0,1,….n-1这n个数字排成一个圆圈,从数字0开始每次从这个圆圈里删除第m个数字。求圆圈里剩下的最后一个数字。
int LastNumLeft(int n, int m){ if (n < 1 || m < 1) return -1; list<int> li; for (int i = 0; i < n; ++i) li.push_back(i); list<int>::iterator it = li.begin(); while (li.size()>1) { for (int i=0;i<m-1;++i) { if (it == li.end()) it = li.begin(); else { it++; if (it == li.end()) it = li.begin(); } } it = li.erase(it); if (it == li.end()) //删除为链表最后一个结点,赋值begin() it = li.begin(); } return li.front();}
- 数据结构之链表编程(C++)
- 数据结构之链表(C/C++)
- 数据结构之链表(c)
- C - 数据结构之链表
- 数据结构之单循环链表C++(模板)
- 数据结构学习笔记之链表(C语言版)
- 数据结构之双向链表(C语言实现)
- 数据结构(C语言)之链表(单、双链表)
- c语言数据结构之链表
- 数据结构之c语言链表
- C语言数据结构之双向链表
- 数据结构之链表(C实现)
- C 语言 数据结构之双向链表
- C - 数据结构之 循环链表
- 数据结构之链表——c
- 数据结构之链表(C实现)
- c语言数据结构之通用链表
- 数据结构(c语言版)之顺序表
- 关于引用资源文件挂掉的问题解决
- vector 中resize和reserve的区别
- php生成EAN_13标准的条形码
- 【HDU 1087 】Super Jumping! Jumping! Jumping! 【LIS 的变形】
- 使用PolySpace进行模型的检测
- 数据结构之链表编程(C++)
- 二叉排序树
- 从传统的版本管理看SVN
- 冒泡排序改进之梳排序实现
- [Leetcode] problem 13之Roman to Integer
- 开始创作字符风格 RPG 游戏《Dragon Rider》
- 编译安装php报错PHP configure: error: mcrypt.h not found. Please reinstall libmcrypt. 解决办法
- NYOJ666
- 在内存中显示位图