单链表的实现(给定某结点,删除它;给定某结点,在他前面插入一个结点等)

来源:互联网 发布:指针处理数组 编辑:程序博客网 时间: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);*/}
阅读全文
0 0
原创粉丝点击