一.概念
双向链表和单向链表相比,每一个结点都多了一个指针域,即共有两个指针域,一个指向后继结点,另一个指向前驱结点,如图
因此双向链表可以向两个方向移动,不像单向链表那样只能从头到尾进行查找,双向链表相当于牺牲空间换取时间的做法。当双向链表的头尾相连时,形成了双向循环链表。当双向循环链表为空时,其头结点的两个指针域均指向自己,不为空时,形成循环链表的具体做法是:最后一个结点的后继指针指向头结点后的第一个结点,即第一个存放元素的结点;第一个存放元素的结点的前驱指针指向最后一个结点,形成闭环,即所有存放有效数据的结点形成闭环。
二.实践
声明:DouLinkList.h
//
// Created by 开机烫手 on 2018/3/13.
//
#ifndef LINEARLIST_DOULINKLIST_H
#define LINEARLIST_DOULINKLIST_H
namespace xq {
typedef struct douNode {
int data;
struct douNode *prior;
struct douNode *next;
} NODE;
class DouLinkList {
private:
NODE *head;
int len;
public:
DouLinkList(int n = 0);
~DouLinkList();
void print();
void printReverse();
int getLength();
int getElem(int);
bool insert(int, int);
bool delete_(int, int *);
bool isEmpty();
bool clearList();
};
}
#endif //LINEARLIST_DOULINKLIST_H
定义:DouLinkList.cpp
//
// Created by 开机烫手 on 2018/3/13.
//
#include "DouLinkList.h"
#include <iostream>
using namespace std;
using namespace xq;
DouLinkList::DouLinkList(int n) {
if (n == 0) {
head = new NODE;
head->next = head;
head->prior = head;
len = 0;
return;
}
len = 0;
head = new NODE;
NODE *p = head, *q;
for (int i = 0; i < n; i++) {
q = new NODE;
p->next = q;
q->data = i + 1;
q->prior = p;
p = q;
len++;
}
p->next = head->next;
head->next->prior = p;
}
DouLinkList::~DouLinkList() {
}
void DouLinkList::print() {
if (head->next == head) {
cout << "list is empty !!!" << endl;
return;
}
NODE *p = head->next;
while (p->next != head->next) {
cout << p->data << ' ';
p = p->next;
}
cout << p->data;
cout << endl;
}
void DouLinkList::printReverse() {
if (head->next == head) {
cout << "list if empty !!!" << endl;
return;
}
NODE *p = head->next->prior;
while (p->prior != head->next->prior) {
cout << p->data << ' ';
p = p->prior;
}
cout << p->data;
cout << endl;
}
int DouLinkList::getLength() {
return len;
}
int DouLinkList::getElem(int i) {
if (len == 0 || i <= 0 || i > len)
return -999;
if (i <= len / 2) {
NODE *p = head->next;
int j = 1;
while (p->next && j < i) {
p = p->next;
j++;
}
return p->data;
} else {
NODE *p = head->next->prior;
int j = i;
while (p->prior && (len - j)) {
p = p->prior;
j++;
}
return p->data;
}
}
bool DouLinkList::insert(int i, int e) {
if (i - len > 1 || i <= 0)
return false;
if (len == 0) {
NODE *q = new NODE;
head->next = q;
q->data = e;
q->next = q;
q->prior = q;
len++;
return true;
} else {
if (i <= len+1 / 2) {
NODE *p = head->next;
int j = 1;
while (p->next && j < i) {
p = p->next;
j++;
}
NODE *q = new NODE;
q->data = e;
q->next = p->prior->next;
q->prior = p->prior;
p->prior->next = q;
p->prior = q;
if (i == 1)
head->next = q;
len++;
return true;
} else {
NODE *p = head->next->prior;
int j = i;
while (p->prior && (len - j + 1)) {
p = p->prior;
j++;
}
NODE *q = new NODE;
q->data = e;
q->next = p->next;
q->prior = p;
p->next->prior = q;
p->next = q;
len++;
return true;
}
}
}
bool DouLinkList::delete_(int i, int *e) {
if (i <= 0 || i > len)
return false;
if (i <= len / 2) {
NODE *p = head->next;
int j = 1;
while (p->next && j < i) {
p = p->next;
j++;
}
*e = p->data;
p->prior->next = p->next;
p->next->prior = p->prior;
if (i == 1)
head->next = p->next;
delete p;
len--;
return true;
} else {
NODE *p = head->next->prior;
int j = i;
while (p->prior && (len - j)) {
p = p->prior;
j++;
}
*e = p->data;
p->prior->next = p->next;
p->next->prior = p->prior;
delete p;
len--;
return true;
}
}
bool DouLinkList::isEmpty() {
return len == 0;
}
bool DouLinkList::clearList() {
NODE *p = head->next;
NODE *q;
while (p->next != head->next) {
q = p->next;
delete p;
p = q;
}
delete p;
head->next = head;
head->prior = head;
len = 0;
return true;
}
测试代码:main.cpp
#include <iostream>
//#include "LinkList.h"
#include "DouLinkList.h"
using namespace std;
using namespace xq;
int main() {
cout << "----------List test programe!---------- " << endl;
DouLinkList list2(6);
list2.printReverse();
list2.print();
cout << "list length is " << list2.getLength() << endl;
cout << list2.getElem(1) << endl;
list2.insert(7, 10);
list2.insert(4, 11);
list2.print();
int num = 0;
list2.delete_(1, &num);
list2.print();
cout << "num = " << num << endl;
cout << "list is empty? " << list2.isEmpty() << endl;
list2.clearList();
cout << "list is empty? " << list2.isEmpty() << endl;
list2.insert(1, 3);
list2.insert(1, 4);
list2.insert(1, 5);
list2.print();
return 0;
}
程序输出为:
----------List test programe!----------
6 5 4 3 2 1
1 2 3 4 5 6
list length is 6
1
1 2 3 11 4 5 6 10
2 3 11 4 5 6 10
num = 1
list is empty? 0
list is empty? 1
5 4 3
切记!最重要的是链表生成结束形成闭环时的步骤:最后一个结点p的后继指向第一个存放数据的结点,即p->next = head->next;第一个存放数据的结点的前驱指向最后一个结点,即head->next->prior = p。