单链表操作——交换节点

链表是最为常见,并且经常需要使用到的数据结构之一。对于单链表的基本操作,例如创建链表、插入、删除等都不是特别复杂,但是其实对于链表的操作实际上很多的操作还是有一定的难度,例如上次给出的单链表的逆转,以及这里的单链表交换两个节点。

       单链表的交换节点的含义是:给定一个单链表,要求交换其中的任意两个节点。注意这里链表的头节点是不参与节点交换的。这个看上去是比较简单,但是实现起来却还是需要一定的基本功。

       对于这个问题,关键是要用4个指针来保存两个交换的节点的前后节点位置,具体实现请参见实现源码。实际上,还有一个逻辑更加清晰的实现:只要用两个指针保存当前的两个交换节点的前一个节点,然后依次删除待交换节点,再在记录的前一个节点后交替插入删除的两个节点,也就是实际上将这个过程转化为了对于链表的两个基本操作就可以完成了。但是要注意的是,这个实现中当两个交换节点是相邻节点的时候会出现问题,要单独处理,具体原因手工操作一次即可得知。后一种方法这里就不给出了。

       实现代码中要说明的是,交换链表节点传入的是两个交换节点指针,但是为了测试简单实现,将这两个节点换成了待交换节点的关键字(值域),再到链表中定位。

//Link.h
 
#include <iostream>
 
#include <ctime>
 
struct Node
{
public:
       Node():_val(0),_next(NULL)
       {
 
       }
       Node(int val):_val(val),_next(NULL)
       {
 
       }
       Node(int val,Node* next):_val(val),_next(next)
       {

       }
       ~Node()
       {
              if (_next)
                  delete _next;
       }
public:
       int _val;
       Node* _next;
};
typedef Node* LinkNode;
Node* CreateLink(int len,int MAX_BOUND = 100)
{
       srand((unsigned int)time(NULL));
       LinkNode head = new Node(-1);
       LinkNode tmp = head;
       for (int i = 0; i < len; ++i)
       {
              //tmp = tmp->_next = new Node(rand() % MAX_BOUND);
              tmp = tmp->_next = new Node(i);
       }
       tmp->_next = NULL;
       return head;
}
void ExchLinkNode(const LinkNode head,const LinkNode node1,const LinkNode node2)
{
       //head不准被交换
 
       LinkNode prenode1 = NULL;  //保存待交换节点node1的前一个节点
       LinkNode postnode1 = NULL; //保存待交换节点node1的后一个节点
       LinkNode prenode2 = NULL;  //保存待交换节点node2的前一个节点
       LinkNode postnode2 = NULL; //保存待交换节点node2的后一个节点
       LinkNode tmp = head;
       //不得和头节点交换
       if (node1 == head)
       {
              return ;
       }
       else if (node2 == head)
       {
              return ;
       }
       //自己和自己就不必交换了
       if (node1 == node2)
       {
              return ;
       }
       //节点相邻情况处理
       if (node1->_next == node2)
       {
              tmp = head;
              while (tmp->_next != node1)
              {
                     tmp = tmp->_next;
              }
              prenode1 = tmp;
              postnode2 = node2->_next;
              prenode1->_next = node2;
              node2->_next = node1;
              node1->_next = postnode2;
              return ;
       }
       if (node2->_next == node1)
       {
              tmp = head;
              while (tmp->_next != node1)
              {
                     tmp = tmp->_next;
              }
              prenode2 = tmp;
              postnode1 = node1->_next;
              prenode2->_next = node1;
              node1->_next = node2;
              node2->_next = postnode1;
              return ;
       }
       tmp = head;
       while (tmp->_next != node1)
       {
              tmp = tmp->_next;
       }
       prenode1 = tmp;
       tmp = head;
       while (tmp->_next != node2)
       {
              tmp = tmp->_next;
       }
       prenode2 = tmp;
       postnode1 = node1->_next;
       postnode2 = node2->_next;
       //交换节点
       prenode1->_next = node2;
       node2->_next = postnode1;
       prenode2->_next = node1;
       node1->_next = postnode2;
}

总结链表节点交换时候至少需要考虑的情况有(这里不进行必要的参数验证):

1)  链表头节点不参与任何交换;

2)  节点相同就不必进行交换;

3)  节点相邻的时候要特殊处理。

之所以对单链表的节点交换作了较多的描述,是因为单链表的节点交换作是链表排序中

的基本操作,具体将在相应的实现中描述。因此这里给出的交换节点函数传入的直接就是链表和两个节点,如果传入的是节点的关键字,先遍历链表定位就可以了,相关数据结构的定义参见《单链表操作——交换节点》。


  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
整合了这篇文章,补全了所有的基本操作(该文中只给出了其中12种,这里提供完整的19种功能)http://www.cnblogs.com/lifuqing/archive/2011/08/20/List.html 快速排序部分参考了 http://blog.csdn.net/pinkrobin/article/details/5456094 1.初始化线性表,即置单链表的表头指针为空 2.创建线性表,此函数输入负数终止读取数据 3.打印链表,链表的遍历 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为一个空表 5.返回单链表的长度 6.检查单链表是否为空,若为空则返回1,否则返回0 7.返回单链表中第pos个结点中的元素,若pos超出范围,则停止程序运行 8.从单链表中查找具有给定值x的第一个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL 9.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 10.向单链表的表头插入一个元素 11.向单链表的末尾添加一个元素 12.向单链表中第pos个结点位置插入元素为x的结点,若插入成功返回1,否则返回0 13.向有序单链表中插入元素x结点,使得插入后仍然有序 14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停止程序运行 15.从单链表中删除表尾结点并返回它的值,若删除失败则停止程序运行 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停止程序运行 17.从单链表中删除值为x的第一个结点,若删除成功则返回1,否则返回0 18.交换2个元素的位置 19.将线性表进行快速排序
/* 1.初始化线性表,即置单链表的表头指针为空 *//* 2.创建线性表,此函数输入负数终止读取数据*//* 3.打印链表,链表的遍历*//* 4.清除线性表L中的所有元素,即释放单链表L中所有的结点,使之成为一个空表 *//* 5.返回单链表的长度 *//* 6.检查单链表是否为空,若为空则返回1,否则返回0 *//* 7.返回单链表中第pos个结点中的元素,若pos超出范围,则停止程序运行 *//* 8.从单链表中查找具有给定值x的第一个元素,若查找成功则返回该结点data域的存储地址,否则返回NULL *//* 9.把单链表中第pos个结点的值修改为x的值,若修改成功返回1,否则返回0 *//* 10.向单链表的表头插入一个元素 *//* 11.向单链表的末尾添加一个元素 *//* 12.向单链表中第pos个结点位置插入元素为x的结点,若插入成功返回1,否则返回0 *//* 13.向有序单链表中插入元素x结点,使得插入后仍然有序 *//* 14.从单链表中删除表头结点,并把该结点的值返回,若删除失败则停止程序运行 *//* 15.从单链表中删除表尾结点并返回它的值,若删除失败则停止程序运行 *//* 16.从单链表中删除第pos个结点并返回它的值,若删除失败则停止程序运行 *//* 17.从单链表中删除值为x的第一个结点,若删除成功则返回1,否则返回0 *//* 18.交换2个元素的位置 *//* 19.将线性表进行快速排序 */

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值