双向链表的逆置(两种)

#include<iostream>
#include<string>
using namespace std;
template<class T>
struct LinkNode
{
	LinkNode(const T& x)
		:_data(x)
		, _prev(NULL)
		, _next(NULL)
	{

	}
	T _data;
	LinkNode<T>* _prev;
	LinkNode<T>* _next;
};
template<class T>
class List
{
public:
	List()
		:_head(NULL)
		, _tail(NULL)
	{
	}
	void PushBack(const T& x)
	{
		if (_head == NULL)
		{
			_head = new LinkNode<T>(x);
			_tail = _head;
		}
		else
		{
			LinkNode<T>* tmp = new LinkNode<T>(x);
			_tail->_next = tmp;
			tmp->_prev = _tail;
			_tail = _tail->_next;
		}

	}
	void PopBack()
	{
		if (_head == NULL)
		{
			return;
		}
		else if (_head == _tail)
		{
			delete _head;
			_head = _tail = NULL;
		}
		else
		{
			LinkNode<T> *del = _tail;
			_tail->_prev->_next = NULL;
			_tail = _tail->_prev;
			delete del;
		}
	}
	void PushFront(const T& x)
	{
		if (_head == NULL)
		{
			_head = new LinkNode<T>(x);
			_tail = _head;
		}
		else
		{
			LinkNode<T>* tmp = new LinkNode<T>(x);
			tmp->_next = _head;
			_head->_prev = tmp;
			_head = tmp;
		}
	}
	void PopFront()
	{
		if (_head == NULL)
		{
			return;
		}
		else if (_head == _tail)
		{
			delete _head;
			_head = _tail = NULL;
		}
		else
		{
			LinkNode<T> *del = _head;
			_head->_next->_prev = NULL;
			_head = _head->_next;
			delete del;
		}
	}
	~List()
	{
		while (_head)
		{
			Destory();
		}
		_head = _tail = NULL;
	}
	void Print()
	{
		LinkNode<T>* cur = _head;
		while (cur)
		{
			cout << (cur->_data) << "->";
			cur = cur->_next;
		}
		cout << "NULL" << endl;
	}
	void  Reverse_()
	{
		if (_head == NULL || _head == _tail)
			return;
		LinkNode<T>* left = _head;
		LinkNode<T>* right = _tail;
		while (left != right&&left->_prev != right)//保证奇偶节点都没问题
		{
			swap(left->_data, right->_data);
			left = left->_next;
			right = right->_prev;
		}

	}
	void  Reverse()
	{
		if (_head == NULL || _head == _tail)
			return;
		LinkNode<T>* cur = _head;
		while (cur)
		{
			swap(cur->_prev, cur->_next);
			cur = cur->_prev;//注意
		}
		swap(_head, _tail);
	}
protected:
	void Destory()
	{
		if (_head == NULL)
		{
			return;
		}
		else if (_head == _tail)
		{
			delete _head;
			_head = _tail = NULL;
		}
		else
		{
			LinkNode<T>* del = _head;
			_head = _head->_next;
			_head->_prev = NULL;
			delete del;
		}
	}
protected:
	LinkNode<T>* _head;
	LinkNode<T>* _tail;
};

void  Test1()
{
	List<int> k;
	k.PushBack(1);
	k.PushBack(2);
	k.PushBack(3);
	k.PushBack(4);
	k.PushBack(5);
	k.PushBack(6);

	k.Print();

	k.Reverse_();
	k.Print();

	k.Reverse();
	k.Print();
}
int main()
{
	Test1();
	system("pause");
	return 0;
}

注意测试用例的选取

时间: 2024-10-25 04:04:05

双向链表的逆置(两种)的相关文章

如何在时间复杂度为O(n)空间复杂度为O(1)的情况下完成链表的逆置

问题如题目,首先分析,链表的反转的空间复杂度如果为常数级,那么不可能完成从堆中申请数据来完成链表的反转工作,所以问题就转化为了如何将原链表修改/拆解为逆置的链表: 函数形式假定如下  void Inverse(List*&head)//////修改原链表为逆置 第一种办法最简单,就是在创建一个局部变量 List*tail 作为产生的新链表的“尾部”,再设置一个“游标”指针用于指向当前正在访问的链表单元,然后按顺序循环遍历链表,在遍历的同时将正在访问的链表单元添加到新链表尾部的“tail”指针前面

【C++】实现双向链表的所有操作,包括逆置双链表(三种方法)

建立源文件List.cpp include "List.h" int main() {     Test();     system("pause");     return 0; } 建立头文件List.h #ifndef __LISH_H__ #define __LISH_H__ #include<iostream> using namespace std; typedef int DataType; struct ListNode {     Li

【总结】逆置双向链表的三种方法

双向链表的遍历要比单向链表方便很多,所以逆置方法要比单链表丰富很多,因为可以从后向前遍历,所以可以像逆置数组一样进行操作,也可以根据单链表的特性进行逆置,也可以用双链表独有的特性进行逆置.具体方法如下: 链表的类定义如下: typedef int DataType; class DSNode { public: friend class DNSList; DSNode(DataType x=0) :_data(x), _next(NULL), _prev(NULL) { } private: D

c++中的双向链表写法,主要实现(增删查改,链表逆置,构造函数,运算符重载,等)

本文主要内容 1)介绍c++中双向链表的写法. 2)实现双向链表中数据的增.删.查.改.链表逆置.链表输出 3)介绍类中构造函数.析构函数.运算符重载函数的写法 接下来介绍双向链表的成员函数:这写函数放在头文件中,方便编写 #pragma once #include<iostream> using namespace std; #include<assert.h> typedef int DataType; class ListNode  //节点 { public: ListNo

maven的两种可运行jar打包方式。1、内置依赖,2、外部依赖。

maven打可运行jar包的两种方式 maven常用的普通打包方式分为pom,jar,war等,至于这些打包类型就不介绍啦. 如果不进行特殊配置,那么打包出来的jar包是不可运行的.只能当作普通依赖包使用. 下面就介绍两种maven打可运行jar包的方式: 方式一:内置打包法 <plugins> <!-- 内置打包法 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <!-- 

在jsp中常用的内置对象(5个)小总结和两种页面跳转方式(服务器端调转、客户端跳转)的区别

jsp中常用的几个内置对象: 一.request对象 主要作用:  (1)获取请求页面的信息   比如:request.getParameter("参数名");  (2)获取客户端的信息   比如:request.getRemoteAddr();//获取客户端的IP地址.  (3)处理乱码   比如:request.setCharacterEncoding("UTF-8"); 二.response对象 主要作用:  (1)请求重定向(客户端跳转)  response

Leetcode:Swap Nodes in Pairs 单链表相邻两节点逆置

Given a linked list, swap every two adjacent nodes and return its head. For example, Given 1->2->3->4, you should return the list as 2->1->4->3. Your algorithm should use only constant space. You may not modify the values in the list, on

统计逆序对的两种解法

统计逆序对的两种解法 归并排序(mergeSort) 逆序对定义 \(i<j\) 但\(a[i]>a[j]\),假设我们分别使得通过mergeSort使得左右半边有序 即\(a[1]...a[mid]\) 递增, \(a[mid+1]....a[n]\)递增,我们需要通过merge操作,完成整个的排序和新增逆序对的计数,较小值出现在左半边记为 a[i],出现在右半边即为 a[j],那么每次出现在右半边,意味左半边比a[i]大的数都比a[j]大,由此可以统计逆序对 HDU1394 代码实现 #i

javade多任务处理之Executors框架(线程池)实现的内置几种方式与两种基本自定义方式

一 Executors框架(线程池) 主要是解决开发人员进行线程的有效控制,原理可以看jdk源码,主要是由java.uitl.concurrent.ThreadPoolExecutor类实现的,这里只列出简单用法 根据Executors可以创建不同功能的线程池,主要有四种: 1 newFixedThreadPool : 返回一个固定数量的线程池,并且池中数量一致保持不变,有任务时如果有空闲线程则立即执行,没有就暂时存放到队列等待空闲线程 //创建一个有10个线程的线程池,任务多于10个会一直等待