单向链表和双向链表区别_双向链表

一开始确实被这个双向链表整晕了,Node里面不停套Node,简直无限套娃,让人不知道该怎么下手。后来看了数据结构与算法分析这本书的图解才算整明白。

我把链表分成了三个部分:

第一部分是Node.Node是一个由两根指针,以及我们需要存储的数据构成的结构体。这个Node就是无限套娃的起源,也是链表用于存储数据的部分——Node里面的两根指针的类型仍旧是Node类型。

第二部分是迭代器,这个迭代器是用来访问链表的存储数据,对其进行读与写。迭代器在这里是一个类,类里面的数据成员仅仅只有一根Node指针。这个Node指针是用来访问Node这个结构体用的接口。迭代器的这一部分的函数都是对一些运算符号的重载,从而实现对顺序查找等等方法。

第三部分就是链表构成自身功能的核心函数,他们的实现是依赖于Node和迭代器这两部分的。

链表内在的成员是这样构造的:

class List {

private:

struct Node;

public:

class const_iterator;

class iterator :public const_iterator;

private:

int theSize;

Node* head;

Node* tail;

};

因为我对泛型编程不熟悉,所以采用int来简化代码。

Node节点是这样构造的:

struct Node {

int data;

Node* prev;

Node* next;

Node(const int& d=0, Node* p = nullptr, Node* n = nullptr) :

data{ d }, prev{ p }, next{ n }{};

Node( int&& d, Node* p = nullptr, Node* n = nullptr) :

data{ std::move(d) }, prev{ p }, next{ n }{}

};

可以看到,一根指针指向前一个节点,另一根指针指向后一个节点。同时在链表中的两根头尾Node指针,其实是用来简化问题的。他们自身是不存储任何数据的。

而迭代器的实现如下:

class const_iterator {

protected:

Node* current;

int& retrieve()const {

return current->data;

}

const_iterator(Node* p) :current{ p } {};

friend class List;

public:

const_iterator() :current{ nullptr } {};

const_iterator(const const_iterator& rhs) :current{ rhs.current } {};

const int& operator*()const {

return retrieve();

}

const_iterator& operator++() {

current = current->next;

return *this;

}

const_iterator operator++(int) {

const_iterator old = *this;

++(*this);

return old;

}

bool operator==(const const_iterator& rhs)const {

return current == rhs.current;

}

bool operator!=(const const_iterator& rhs)const {

return !(*this == rhs);

}

};

class iterator :public const_iterator {

protected:

iterator(Node* p) :const_iterator{ p } {};

friend class List;

public:

iterator() {};

int& operator*() {

return const_iterator::retrieve();

}

const int& operator*()const {

return const_iterator::operator*();

}

iterator& operator++() {

this->current = this->current->next;

return*this;

}

iterator& operator--() {

this->current = this->current->prev;

return *this;

}

iterator operator++(int) {

iterator old = *this;

++(*this);

return old;

}

iterator operator--(int) {

iterator old = *this;

--(*this);

return old;

}

};

iterator可以实现const_iterator的所有功能,从这个意义上iterator IS-A const_iterator,因此采用了继承的手法。同时,迭代器只是一个用来访问数据的接口,因此它的函数大部分都是重载函数。

而接下来就是链表的核心功能:插入和删除。

插入功能:

插入功能的实现可以用这副图来解释:

2a1c8166cb8b5e9a079f99a64cfa95c3.png

6d8cefc928d3f0bb37516ed63efbb2b9.png

因此看图的话代码就是下面的:

iterator insert(iterator itr, const int& x) {

Node* p = itr.current;

theSize++;

return{ p->prev=p->prev->next= new Node{x,p->prev,p} };

}

iterator insert(iterator itr, const int&& x) {

Node* p = itr.current;

theSize++;

return{ p->prev = p->prev->next = new Node{std::move(x),p->prev,p}};

}

至于删除功能,代码如下:

iterator erase(iterator itr) {

Node* p = itr.current;

iterator itRal = p->next;

p->prev->next = p->next;

p->next->prev = p->prev;

delete p;

theSize--;

return itRal;

}

iterator erase(iterator from, iterator to) {

for (iterator itr = from; itr != to; itr++)

itr = erase(itr);

return to;

}

那么现在,已经实现了链表的主要功能,最后,附上链表的全部代码:

class List {

private:

struct Node {

int data;

Node* prev;

Node* next;

Node(const int& d=0, Node* p = nullptr, Node* n = nullptr) :

data{ d }, prev{ p }, next{ n }{};

Node( int&& d, Node* p = nullptr, Node* n = nullptr) :

data{ std::move(d) }, prev{ p }, next{ n }{}

};

public:

class const_iterator {

protected:

Node* current;

int& retrieve()const {

return current->data;

}

const_iterator(Node* p) :current{ p } {};

friend class List;

public:

const_iterator() :current{ nullptr } {};

const_iterator(const const_iterator& rhs) :current{ rhs.current } {};

const int& operator*()const {

return retrieve();

}

const_iterator& operator++() {

current = current->next;

return *this;

}

const_iterator operator++(int) {

const_iterator old = *this;

++(*this);

return old;

}

bool operator==(const const_iterator& rhs)const {

return current == rhs.current;

}

bool operator!=(const const_iterator& rhs)const {

return !(*this == rhs);

}

};

class iterator :public const_iterator {

protected:

iterator(Node* p) :const_iterator{ p } {};

friend class List;

public:

iterator() {};

int& operator*() {

return const_iterator::retrieve();

}

const int& operator*()const {

return const_iterator::operator*();

}

iterator& operator++() {

this->current = this->current->next;

return*this;

}

iterator& operator--() {

this->current = this->current->prev;

return *this;

}

iterator operator++(int) {

iterator old = *this;

++(*this);

return old;

}

iterator operator--(int) {

iterator old = *this;

--(*this);

return old;

}

};

private:

int theSize;

Node* head;

Node* tail;

void init() {

theSize = 0;

head = new Node;

tail = new Node;

head->next = tail;

tail->prev = head;

};

public:

iterator begin() {

return { head->next };

}

const_iterator begin()const {

return{ head->next };

}

iterator end() {

return { tail };

}

const_iterator end()const

{

return{ tail };

};

int size()const {

return theSize;

}

bool empty()const {

return size() == 0;

}

int& front() {

return *begin();

}

const int& front()const {

return *begin();

}

List() {

init();

}

List(const List& rhs) {

init();

for (auto& x : rhs) {

push_back(x);

}

}

List& operator=(const List& rhs) {

List copy(rhs);

std::swap(*this, copy);

return *this;

}

List(List&& rhs):theSize{rhs.theSize},head{rhs.head},tail{rhs.tail}

{

rhs.theSize = 0;

rhs.head = nullptr;

rhs.tail = nullptr;

}

~List() {

clear();

delete head;

delete tail;

}

iterator insert(iterator itr, const int& x) {

Node* p = itr.current;

theSize++;

return{ p->prev=p->prev->next= new Node{x,p->prev,p} };

}

iterator insert(iterator itr, const int&& x) {

Node* p = itr.current;

theSize++;

return{ p->prev = p->prev->next = new Node{std::move(x),p->prev,p}};

}

iterator erase(iterator itr) {

Node* p = itr.current;

iterator itRal = p->next;

p->prev->next = p->next;

p->next->prev = p->prev;

delete p;

theSize--;

return itRal;

}

iterator erase(iterator from, iterator to) {

for (iterator itr = from; itr != to; itr++)

itr = erase(itr);

return to;

}

void push_back(const int &x) {

insert(end(), x);

}

void push_back(const int&& x) {

insert(end(), std::move(x));

}

int& back() {

return *--end();

}

void push_front(const int&x) {

insert(begin(), x);

}

void push_front( int&& x) {

insert(begin(), std::move(x));

}

void pop_front() {

erase(begin());

}

void pop_back() {

erase(--end());

}

void clear() {

while (!empty())

pop_front();

}

};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值