【练习3.3】

通过之调整指针(而不是数据)来交换两个相邻的元素,使用

a.单链表

b.双链表

Answer:

先放测试代码,折叠标题可以看到分别是哪种链表的测试。

实测可满足题意,但单链表和双链表的两段代码是分开实现的,所以需要分开测试。

如果要合在一起的话,需要改一下头文件包含以及命名空间。

单链表测试代码:

 #include <iostream>
#include "linklist.cpp"
using namespace std;
using namespace linklist;
template class List<int>;
int main(void)
{
List<int> number; //原始链表
cout << "/*additem()*/" << endl;
number.additem();
number.additem();
number.additem();
number.additem();
number.additem();
number.additem();
number.additem();
number.traverse();
cout << "\n/*end*/\n\n" << endl; //测试交换顺序,头节点与中间节点各一
cout << "/*swappos()*/" << endl;
number.swappos(number.find());
number.swappos(number.find());
number.traverse();
cout << "/*end*/\n\n" << endl; system("pause");
}

双链表测试代码:

 #include <iostream>
#include "double_linklist.cpp"
using namespace std;
using namespace doublelinklist;
template class DList<int>;
int main(void)
{
DList<int> number; //测试插入
cout << "/*additem()*/" << endl;
number.additem();
number.additem();
number.additem();
number.additem();
number.additem();
number.additem();
number.additem();
number.traverse();
cout << "\n/*end*/\n\n" << flush; //测试交换函数
cout << "/*swappos*/" << endl;
//测试头节点
number.swappos(number.find());
number.traverse();
cout << endl;
//测试邻接尾节点的中间节点
number.swappos(number.find());
number.traverse();
cout << endl;
//测试中间节点
number.swappos(number.find());
number.traverse();
cout << endl;
//测试尾节点
number.swappos(number.find());
cout << "/*end*/\n\n" << flush; system("pause");
}

通过交换指针交换节点直观上还是比较容易的,但是需要比较细致否则容易做错。

因为注释不太好解释,所以代码上就不放注释了,直接上图比较直观。

首先以单链表为例,pos是头节点的情形可以当做一种特殊情况,处理方法比一般情况要简单。

更一般地,通过迭代找到pos的前驱,在后面的实现代码里记为iter变量,然后几个指针的变化关系如下图。

最后的问号代表该处可能是一个节点,也可能是nullptr,但是对于单链表而言没有影响。

考虑双链表时,同样不考虑pos是头指针的情况(当然在代码里还是要表现的),有三点细微的不一致

①、不需从链表头迭代寻找pos的前驱iter,在没有修改前向指针的情况下,可以把单链表书写中的iter全部写成pos->prev

②、按单链表的方法,修改完后向指针后,需要调整前向指针

③、尾部的问号节点如果为空,则会对rear的位置产生影响;如果不为空,则需调整该问号节点的前向指针

简图如下:

最后是实现代码,将其分别复制进此前对应的例程中,函数的声明请自行补充。

单链表实现代码:

 //练习3.3新增,交换相邻节点
template <typename T> bool List<T>::swappos(Node<T>* pos)
{
if (pos->next == nullptr)
{
cout << ("Illegal!") << endl;
return false;
}
if (pos == front)
{
front = front->next;
pos->next = front->next;
front->next = pos;
}
else
{
Node<T>* iter = front;
while (iter->next != pos)
iter = iter->next;
if (iter == nullptr)
{
cout << ("Illegal!") << endl;
return false;
}
else
{
iter->next = pos->next;
pos->next = pos->next->next;
iter->next->next = pos;
}
}
return true;
}

双链表实现代码:

 //练习3.3新增,通过交换指针交换节点
//不检测pos位置是否确实在双链表中(否则速度比单链表更慢,失去意义)
template <typename T> bool DList<T>::swappos(Node<T>* pos)
{
if (pos->next == nullptr)
{
cout << "Illegal" << endl;
return false;
}
if (pos == front)
{
front = front->next;
front->prev = nullptr;
pos->next = front->next;
pos->prev = front;
front->next = pos;
}
else
{
//后向指针调整
pos->prev->next = pos->next;
pos->next = pos->next->next;
pos->prev->next->next = pos;
//前向指针调整
pos->prev->next->prev = pos->prev;
pos->prev = pos->prev->next; }
//判断尾指针是否为空
if (pos->next == nullptr)
rear = pos;
else
pos->next->prev = pos;
return true;
}

【Weiss】【第03章】练习3.3:通过交换指针交换单/双链表元素的更多相关文章

  1. 【Weiss】【第03章】练习3.21:单数组模拟双栈

    [练习3.21] 编写仅用一个数组而实现两个栈的例程.除非数组的每一个单元都被使用,否则栈例程不能有溢出声明. Answer: 很简单,一个栈从数组头起,一个栈从数组尾起,分别保留左右栈头索引. 如l ...

  2. 【Weiss】【第03章】练习3.4、3.5:有序链表求交、并

    [练习3.4] 给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∩L2的过程. [练习3.5] 给定两个已排序的表L1和L2,只使用基本的表操作编写计算L1∪L2的过程. 思路比较简单,测 ...

  3. 第03章 AOP前奏

    第03章 AOP前奏 提出问题 ●情景:数学计算器 ●要求 ①执行加减乘除运算 ②日志:在程序执行期间追踪正在发生的活动 ③验证:希望计算器只能处理正数的运算 ●常规实现 ●问题 ○代码混乱:越来越多 ...

  4. 第03章_基本的SELECT语句

    第03章_基本的SELECT语句 1. SQL概述 1.1 SQL背景知识 1946 年,世界上第一台电脑诞生,如今,借由这台电脑发展起来的互联网已经自成江湖.在这几十年里,无数的技术.产业在这片江湖 ...

  5. suse 12 二进制部署 Kubernetets 1.19.7 - 第03章 - 部署flannel插件

    文章目录 1.3.部署flannel网络 1.3.0.下载flannel二进制文件 1.3.1.创建flannel证书和私钥 1.3.2.生成flannel证书和私钥 1.3.3.将pod网段写入et ...

  6. 【Weiss】【第03章】增补附注

    基本上每章到增补附注这里就算是结束了. 根据设想,每章的这一篇基本上会注明这一章哪些题没有做,原因是什么,如果以后打算做了也会在这里补充. 还有就是最后会把有此前诸多习题的代码和原数据结构放整理后,以 ...

  7. 【Weiss】【第03章】练习3.25:数组模拟队列

    [练习3.25] 编写实现队列的例程,使用 a.链表 b.数组 Answer: 在这章一开头就已经写了个链表的队列例程了,所以实际上只要做b小题就可以. 数组模拟队列和链表的两点小不同是: ①.数组空 ...

  8. 【Weiss】【第03章】练习3.16:删除相同元素

    [练习3.16] 假设我们有一个基于数组的表A[0,1...N-1],并且我们想删除所有相同的元素. LastPosition初始值为N-1,但应该随着相同元素被删除而变得越来越小. 考虑图3-61中 ...

  9. 【Weiss】【第03章】练习3.26:双端队列

    [练习3.26] 双端队列(deque)是由一些项的表组成的数据结构,对该数据结构可以进行下列操作: Push(X,D):将项X插入到双端队列D的前端. Pop(D):从双端队列D中删除前端项并返回. ...

随机推荐

  1. Archlinux系统运维

    本文将针对Archlinux下的系统运维进行介绍. 内核相关 查看当前内核版本 123 uname -r------------------------------------------------ ...

  2. 一分钟搞定pychram远程调试和同步代码

    首先说一下需求,否则很多人都不知道pycharm这个远程同步和调试到底是干嘛使的. 需求很简单,我想要在本地的windows机器上跑一个程序,但是程序运行会加载一些很占内存的树型数据结构,称其为tre ...

  3. 奇葩念头:微信能取代WP应用吗

         墙倒众人推,原本是再平常不过的事,但每次发生都显得特别凄凉--就和楼市买房买涨不买跌一样,在互联网行业,用户数量越多的产品或服务,就会越受到行业和大众青睐.而越是小众的产品或服务,虽然是要走 ...

  4. windows的各种扩展名详解

    Windows系统文件按照不同的格式和用途分很多种类,为便于管理和识别,在对文件命名时,是以扩展名加以区分的,即文件名格式为: 主文件名.扩展名.这样就可以根据文件的扩展名,判定文件的种类,从而知道其 ...

  5. 从846家初创倒下 看A轮融资后的悬崖

    看A轮融资后的悬崖" title="从846家初创倒下 看A轮融资后的悬崖"> 相比往年,今年的寒冷冬天来得更早.在互联网行业,今年的"大雪"更 ...

  6. Emacs key bindings for vim users

    Emacs key bindings for vim users | Scarletsky 盒子 盒子 博客 分类 标签 关于 RSS 搜索 文章目录 简介 Emacs 是一个文本编辑器,号称是伪装成 ...

  7. 在 React Native 中使用 moment.js 無法載入語系檔案

    moment.js 是很常見的日期時間 library,友善的 API 與極佳的執行效率是它的兩大賣點.例如 (new Date()).getFullYear(),如果使用 moment.js 我可以 ...

  8. Job for network.service failed because the control process exited with error code问题

    Job for network.service failed because the control process exited with error code问题 因为是克隆的,所以需要重新修改静 ...

  9. USB小白学习之路(2)端点IN/OUT互换

    端点2(out)和端点6(in)的out_in互换 注:这里的out和in都是以host为标准说的,out是host的out,在设备(Cy7c68013)这里其实是输入端口:in是host的in,在设 ...

  10. 解决getImageData跨域问题

    在项目开发过程中要用到html5增加的getImageData方法来实现刮刮卡的效果,后台上传图片,手机端用手刮.在本地开发没遇到问题,上线之后发现刮不了,提示"Uncaught Secur ...