单链表的实现(给定某结点,删除它;给定某结点,在他前面插入一个结点等)
来源:互联网 发布:指针处理数组 编辑:程序博客网 时间:2024/06/06 02:12
基于C++语言实现单链表(利用模板)
首先,我们要搞清楚单链表的特征,在什么情况下适合用该数据结构。
1.链表在内存上的存放是不连续的,所以不能依赖下标来寻址
由于它的内存结构分布,决定了它适用于插入删除较多的情况(时间复杂度O(1))
现在我们来研究关于单链表的相关问题:具体代码在结尾
1.判断一个单链表是否有环
利用快慢指针(slow,fast),起始都指向头,slow一次走一个结点,fast一次走两个结点,当slow==fast时,跳出循环,if(fast==NULL||fast->next==NULL)则说明无环,返回NULL,否则返回fast->next(此为进入环的第一个结点)。在此也可返回bool值,但为了代码的复用,返回了fast->next或者NULL。具体操作需要根据实际要求。代码在最后。
2.只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点。
要删除一个结点,必须知道他的前驱结点。所以在此,将该节点的后一个结点的数据域赋值给该结点,然后删除该节点的后一个结点即可(缺陷,不能删除最后一个结点)
3.只给定单链表中某个结点p(非空结点),在p前面插入一个结点
创建一个新结点,连接到该结点之后,将该结点的数据域赋值给新结点的数据域,再将要插入的数据域赋值给该结点
4.给定两个单链表(head1, head2),检测两个链表是否有交点,如果有返回第一个交点。
只需要将两个链表相连判断是否有环,则可解决,调用功能1即可
5.单链表的逆置
①利用头插进行逆置
②利用前后指针进行逆置
6.已知递增有序的单链表 A,B 和C 分别存储了一个集合,设计算法实现 A:=A∪(B∩C)并使求解结构 A 仍保持递增。要求算法的时间复杂度为 O(|A|+|B|+|C|)。其中,|A|为集合A 的元素个数。
都为有序单链表,则进行遍历的时候不需要进行重复遍历。
#include <iostream>using namespace std;template <typename T>class Link;template <typename T>class Node{private: T _data; Node *_next;public: Node(T val = T()):_data(val),_next(NULL) { } friend class Link<T>;};//带头节点的单链表的实现。template <typename T>class Link{public: Link() { _head = new Node<T>(); } /*~Link() { Node<T>* pcr = _head->_next; while(pcr != NULL) { Node<T> *next = pcr->_next; _head->_next = next; delete pcr; pcr = next; } }*/ void insertHead(T val); void insertTail(T val); void deleteNode(T val); Node<T>* Search(T val); //查询val对应的节点,有则返回节点的地址,没有则返回NULL; Node<T>* IsExitsLoop(); //检测是否有环。 void inverse(); void show(); //打印链表的所有节点 void show1(Node<T>* p) //只打印p指向的节点的数据 { if(p != NULL) { cout<<p->_data<<endl; } } void deleteNode(Node<T> *p);//只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点。 void insertNode(Node<T> *p,T val);//只给定单链表中某个结点p(非空结点),在p前面插入一个结点 Node<T>* intersection (Link<T> list2);//给定两个单链表(head1, head2),检测两个链表是否有交点,如果有返回第一个交点。 void merge(Link<T> list1,Link<T> list2); //已知递增有序的单链表 A,B 和C 分别存储了一个集合,设计算法实现 A:=A∪(B∩C) , //并使求解结构 A 仍保持递增。要求算法的时间复杂度为 O(|A|+|B|+|C|)。其中,|A|为集合A 的元素个数。private: Node<T>* _head;};template <typename T>void Link<T>::show(){ Node<T>* pcr = _head->_next; while(pcr != NULL) { cout<<pcr->_data<<" "; pcr = pcr->_next; } cout<<endl;}//template <typename T>//void Link<T>::show1(Node *p)//{// if(p != NULL)// {// cout<<p->_data<<endl;// }//}template <typename T>void Link<T>::insertHead(T val){ Node *pcr = new Node(val); pcr->_next = _head->_next; _head->_next = pcr;}template <typename T>void Link<T>::insertTail(T val){ Node<T> *pcr = new Node<T>(val); Node<T> *p = _head; while(p->_next != NULL) { p = p->_next; } p->_next = pcr;}template <typename T>void Link<T>::deleteNode( T val){ Node *pcr = _head; while(pcr->_next != NULL) { if(pcr->_next->_data == val) { Node *p = pcr->_next; pcr->_next = p->_next; delete p; return; } pcr = pcr->_next; }}#if 0template <typename T>void Link<T>::inverse() //单链表的逆置-->最简单的方法,利用头插法,进行逆置。{ if(_head->_next==NULL || _head->_next->_next==NULL) { return ; } Node *pcr = _head->_next;; _head->_next = NULL; while(pcr!=NULL) { insertHead(pcr->_data); pcr = pcr->_next; }}#endiftemplate <typename T>void Link<T>::inverse() //利用前后指针,来逆置(稍微麻烦){ if(_head->_next==NULL || _head->_next->_next==NULL) { return ; } Node *after = _head->_next; Node *front = _head; front->_next = NULL; while(after != NULL) { front = after; after = after->_next; front->_next = _head->_next; _head->_next = front; }}template <typename T>Node<T>* Link<T>::Search(T val){ Node<T>* p = _head->_next; while(p != NULL) { if(p->_data == val) { return p; } p = p->_next; } return NULL;}//------------------------------单链表的相关经典问题---------------------------------------//给定单链表,检测是否有环。template <typename T>Node<T>* Link<T>::IsExitsLoop() //利用快慢指针进行解析。{ Node<T> *fast = _head; Node<T> *slow = _head; while(fast != NULL && fast->_next != NULL) { slow = slow->_next; fast = fast->_next->_next; if(slow == fast) { break; } } if(fast==NULL || fast->_next ==NULL) { return NULL; } else { return fast; }}//给定两个单链表(head1, head2),检测两个链表是否有交点,如果有返回第一个交点。template <typename T>Node<T>* Link<T>::intersection (Link<T> list2){ Node<T> *p = _head->_next; while(p->_next != NULL) { p=p->_next; } p->_next = list2._head->_next; Node<T> *tmp = IsExitsLoop(); if(tmp != NULL)//有交点 { return tmp->_next; } else { return NULL; }}//只给定单链表中某个结点p(并非最后一个结点,即p->next!=NULL)指针,删除该结点。template <typename T>void Link<T>::deleteNode(Node<T>* p){ Node<T>* q = p->_next; p->_data = q->_data; p->_next = q->_next; delete q; q= NULL;}//只给定单链表中某个结点p(非空结点),在p前面插入一个结点template <typename T>void Link<T>::insertNode(Node<T>* p,T val) { Node<T>* q = new Node<T>(val); q->_next = p->_next ; p->_next = q; q->_data = p->_data; p->_data = val;}////已知递增有序的单链表 A,B 和C 分别存储了一个集合,设计算法实现 A:=A∪(B∩C) ,//并使求解结构 A 仍保持递增。要求算法的时间复杂度为 O(|A|+|B|+|C|)。其中,|A|为集合A 的元素个数。template <typename T>void Link<T>::merge(Link<T> list1,Link<T> list2){ Node<T>* p_list1 = list1._head->_next; Node<T>* p_list2 = list2._head->_next; Node<T>* p_head = _head; while(p_list1 != NULL || p_list2 != NULL ) { if(p_list1->_data > p_list2->_data) { p_list2 = p_list2->_next; } else if(p_list1->_data < p_list2->_data) { p_list1 = p_list1->_next; } else { while(p_head->_next != NULL) { if(p_head->_next->_data > p_list1->_data ) { insertNode(p_head->_next,p_list1->_data); } else if(p_head->_next->_data < p_list1->_data) { p_head = p_head->_next; } else { p_head = p_head->_next; break; } } p_head->_next = new Node<T>(p_list1->_data); p_list2 = p_list2->_next; p_list1 = p_list1->_next; } }}int main(){ Link<int> list; /*list.insertHead(1); list.insertHead(2); list.insertHead(3); list.insertHead(4);*/ list.insertTail(1); list.insertTail(3); list.insertTail(5); list.insertTail(7); list.show(); Link<int> list1; list1.insertTail(3); list1.insertTail(4); list1.insertTail(5); list1.insertTail(7); list1.insertTail(8); Link<int> list2; list2.insertTail(2); list2.insertTail(3); list2.insertTail(5); list2.insertTail(6); list2.insertTail(7); list2.insertTail(8); list.merge(list1,list2); list.show(); /*Node<int>* p = list.intersection(list1); if(p != NULL ) { list.show1(p); } list.show();*/ /*list.inverse(); list.show();*/ /*list.deleteNode(4); list.show();*/ //Node<int>* p = list.Search(4); //list.show1(p); //Node<int>* q = list.Search(1); //list.deleteNode(q); //list.insertNode(q,0); //list.show(); //list.show1(q); //p->_next = q; /* Node<int> *s; if(s = list.IsExitsLoop()) { cout<<"该链表有环"<<endl; } else { cout<<"该链表无环"<<endl; } list.show1(s);*/}
- 单链表的实现(给定某结点,删除它;给定某结点,在他前面插入一个结点等)
- 018给定二叉查找树的一个结点, 写一个算法查找它的“下一个”结点“(keep it up)
- 给定链表的头指针和一个结点指针,在O(1) 时间删除该结点
- 给定链表的头指针和一个结点指针,在O(1) 时间删除该结点
- 给定链表的头指针和一个结点指针,在O(1)时间删除该结点
- 给定链表的头指针和一个结点指针,在O(1)时间删除该结点。
- 给定链表的头指针和一个结点指针,在O(1)时间删除该结点
- 13\给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点,
- 给定单链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该节点
- 给定链表中间某结点指针,删除链表中该结点
- 给定链表中间某结点指针,删除链表中该结点
- 给定一个节点指针 删除单链中当前结点
- 题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。
- 给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点
- 二叉树的祖先结点,删除,插入,查找,前驱结点,后继结点等
- LinkLists 删除链表中的一个给定指针的结点 @CareerCup
- 二叉树寻找给定结点p的下一个结点
- 输出二叉树中中序遍历中给定结点的下一个结点
- 秋招~~~
- 基本数论入门(快速幂+扩展欧几里得)
- 第三方框架中关于HUD有MBProgressHUD和SVProgressHUD
- stack-structured algorithm and queue-structured algorithm
- JAVA网络编程入门
- 单链表的实现(给定某结点,删除它;给定某结点,在他前面插入一个结点等)
- python os.path模块常用方法
- FileProvider的Server和Client
- 实验二(2)用单链表实现信息操作
- SVProgressHUD(2.0.3)原来是这样
- A few useful things to learn about ML
- 游戏设计之我见 —— Strike Vector EX游玩心得以及思考
- Qt 学习之路 2(62):保存 XML
- c++知识点---类模板的使用