数据结构基础(9) --单链表的设计与实现(2)之高级操作

链表的链接:

    将第二条链表的所有内容链接到第一条链表之后, 其完整实现代码与解析如下:

  1. //链表的链接  
  2. template <typename Type>  
  3. void MyList<Type>::concatenate(const MyList<Type> &list)  
  4. {  
  5.     if (isEmpty())//如果自己的链表为空  
  6.     {  
  7.         first = list.first;  
  8.         return ;  
  9.     }  
  10.     else if (list.isEmpty())    //如果第二条链表为空  
  11.     {  
  12.         return ;  
  13.     }  
  14.   
  15.     Node<Type> *endNode = first->next;  
  16.     //找到第一条链表的末尾节点  
  17.     while (endNode->next != NULL)  
  18.     {  
  19.         endNode = endNode->next;  
  20.     }  
  21.   
  22.     //找到第二条链表的第一个真实元素  
  23.     Node<Type> *secondListNode = (list.first)->next;  
  24.     //注意: 需要将第二个链表中的元素值copy出来  
  25.     //不能直接将第二条链表的表头链接到第一条链表的表尾  
  26.     //不然在析构函数回收内存时会发生错误(即:同一段内存释放两次)  
  27.     while (secondListNode != NULL)  
  28.     {  
  29.         Node<Type> *newNode = new Node<Type>(secondListNode->data);  
  30.         newNode->next = NULL;  
  31.         endNode->next = newNode;  
  32.   
  33.         //两条链表同时前进  
  34.         endNode = endNode->next;  
  35.         secondListNode = secondListNode->next;  
  36.     }  
  37. }  

链表的反转:

基本思想:

    遍历一遍链表,利用一个辅助指针(此处为指针r),存储遍历过程中当前指针指向的下一个元素,然后将当前节点元素的指针反转后,利用已经存储的指针往后面继续遍历。

  1. //链表的反转  
  2. template <typename Type>  
  3. void MyList<Type>::invort()  
  4. {  
  5.     if (!isEmpty())  
  6.     {  
  7.         //p指向正向链表的第一个真实节点  
  8.         //随后, p也会沿正方向遍历到链表末尾  
  9.         Node<Type> *p = first->next;  
  10.   
  11.         //q会成为倒向的第一个真实节点  
  12.         //首先将q设置为NULL: 保证反向之后  
  13.         //最后一个元素的指针域指向NULL, 以表示链表结束  
  14.         Node<Type> *q = NULL;  
  15.         while (p != NULL)  
  16.         {  
  17.             Node<Type> *r = q;  //暂存q当前指向的节点  
  18.             //q后退(沿着正向后退)  
  19.             q = p;  
  20.             //p前进(沿着正向前进), 保证p能够始终领先q一个位置  
  21.             p = p -> next;  
  22.             //将指针逆向反转  
  23.             //注意:一点要保证这条语句在p指针移动之后运行,  
  24.             //不然p就走不了了...(因为q改变了指针的朝向)  
  25.             q -> next = r;  
  26.         }  
  27.   
  28.         //此时q成为反向链表的第一个真实元素  
  29.         //但是为了维护像以前一样的first指针指向一个无用的节点(以使前面的操作不会出错)  
  30.         //于是我们需要将first的指针域指向q  
  31.         first->next = q;  
  32.     }  
  33. }  

链表打印:

    重载MyList<<运算符输出链表所有元素以供测试之用

  1. //显示链表中的所有数据(测试用)  
  2. template <typename Type>  
  3. ostream &operator<<(ostream &os, const MyList<Type> &list)  
  4. {  
  5.     for (Node<Type> *searchNode = list.first -> next;  
  6.             searchNode != NULL;  
  7.             searchNode = searchNode -> next)  
  8.     {  
  9.         os << searchNode -> data;  
  10.         if (searchNode -> next != NULL) //尚未达到链表的结尾  
  11.             cout << " -> ";  
  12.     }  
  13.   
  14.     return os;  
  15. }  

-测试代码:

  1. int main()  
  2. {  
  3.     cout << "------------ 1 ------------" << endl;  
  4.     MyList<int> first;  
  5.     for (int i = 0; i < 5; ++i)  
  6.     {  
  7.         first.insert(i+1, i+1);  
  8.     }  
  9.     first.remove(5);  
  10.   
  11.     MyList<int> second;  
  12.     for (int i = 0; i < 5; ++i)  
  13.     {  
  14.         second.insert(i+6, i+1);  
  15.     }  
  16.     second.insertFront(5);  
  17.     second.insert(88, 7);  
  18.   
  19.     cout << "Before concatenate..." << endl;  
  20.     cout << "first: " << first << endl;  
  21.     cout << "second: " << second << endl;  
  22.   
  23.     cout << "After concatenate..." << endl;  
  24.     first.concatenate(second);  
  25.     cout << "first: " << first << endl;  
  26.     cout << "second: " << second << endl;  
  27.   
  28.   
  29.     cout << "\n------------ 2 ------------" << endl;  
  30.     MyList<char> chList;  
  31.     for (char ch = '0'; ch <= '9'; ++ ch)  
  32.     {  
  33.         chList.insertFront(ch);  
  34.     }  
  35.     cout << "Before invort..." << endl;  
  36.     cout << chList << endl;  
  37.   
  38.     cout << "After invort..." << endl;  
  39.     chList.invort();  
  40.     cout << chList << endl;  
  41.   
  42.     cout << "After remove('5')..." << endl;  
  43.     chList.remove('5');  
  44.     cout << chList << endl;  
  45.   
  46.     cout << "\n------------ 3 ------------" << endl;  
  47.     MyList<double> dList;  
  48.     dList.insert(1.1, 1);  
  49.     dList.insertFront(2.2);  
  50.     cout << dList << endl;  
  51.   
  52.     return 0;  
  53. }  



原文地址:http://blog.csdn.net/zjf280441589/article/details/42430075

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值