1.前言
接着上一次向量的实现,我们这一次来讲讲链表
链表是由节点构成,而每个节点由数据,指向前向节点和后继节点的指针构成。链表分为单向链表、双向链表和循环链表。典型的双向链表模式如下图所示。
同为线性结构的向量与链表,存在一些异同点。下面是向量与链表的对比
首先,向量与链表都属于线性结构
向量支持循秩访问,数据在内存中连续存储,随机访问元素快,但元素增加删除慢
链表支持循位置访问,数据在内存中分散存储,通过指针向量,随机访问元素慢,但元素增加删除快
下面我们以双向链表为例来看看链表的实现
2.节点类的声明
#ifndef LIST_NODE_H
#define LIST_NODE_H
class Node{ //列表的节点类
public:
Node *pred;
Node *succ;
int data;
Node(){}
Node(int e, Node *p = nullptr, Node *s = nullptr):data(e), pred(p), succ(s){}
};
#endif //LIST_NODE_H
3.链表类的声明
#ifndef LIST_LIST_H
#define LIST_LIST_H
#include "Node.h"
class List{ //双向列表
private:
int _size;
Node *header;
Node *trailer;
public:
List(); //构造函数
~List(); //析构函数
int size(); //返回列表大小
Node *first(); //返回首节点位置
Node *last(); //返回末节点位置
Node* insertAsFirst(int e); //作为首节点插入
Node* insertAsLast(int e); //作为末节点插入
Node* insertp(Node *p, int e); //作为前驱节点插入
Node* inserts(Node *p, int e); //作为后继节点插入
int remove(Node *p); //删除节点,返回其数值
Node *find(int const &e, int n, Node *p); //查找节点p的n个前驱中与e相等的最靠后者
int deduplicate(); //列表去重,返回去掉的重复值
void selectsort(); //选择排序
void insertsort(); //插入排序
Node *search(int const &e, int n, Node *p); //查找不大于e的最靠后者
};
#endif //LIST_LIST_H
4.链表类的实现
#include <iostream>
#include "Node.h"
#include "List.h"
using namespace std;
List::List() {
header = new Node; //创建头哨兵节点
trailer = new Node; //创建尾哨兵节点
header->succ = trailer;
header->pred = nullptr;
trailer->pred = header;
trailer->succ = nullptr;
_size = 0;
}
List::~List() {
while(_size-->0)
remove(header->succ); //反复删除首节点
delete header;
delete trailer;
}
int List::size() {
return _size;
}
Node *List::first() {
return header->succ;
}
Node *List::last() {
return trailer->pred;
}
Node *List::insertAsFirst(int e) {
Node *a = new Node(e, header, header->succ);
header->succ->pred = a;
header->succ = a;
_size++;
return a;
}
Node *List::insertAsLast(int e) {
Node *a = new Node(e, trailer->pred, trailer);
trailer->pred->succ = a;
trailer->pred = a;
_size++;
return a;
}
Node *List::insertp(Node *p, int e) {
Node *a = new Node(e, p->pred, p);
p->pred->succ = a;
p->pred = a;
_size++;
return a;
}
Node *List::inserts(Node *p, int e) {
Node *a = new Node(e, p, p->succ);
p->succ->pred = a;
p->succ = a;
_size++;
return a;
}
int List::remove(Node *p) {
int e = p->data;
p->pred->succ = p->succ;
p->succ->pred = p->pred;
delete p;
_size--;
return e;
}
Node *List::find(int const &e, int n, Node *p) {
while(n-->0){
p = p->pred;
if(p->data == e)
return p;
}
return nullptr;
}
int List::deduplicate() {
int _oldsize = _size;
Node *p = first();
for(int r=0; p != trailer; p = p->succ){
if(Node *q = find(p->data, r, p))
remove(q);
else
r++;
}
return _oldsize - _size;
}
void List::selectsort() {
int n = _size;
Node *t = trailer;
while(n-- > 0) {
Node *p = t->pred;
Node *max = p;
while (p != first()) { //找出列表最靠右的最大值
p = p->pred;
if (p->data > max->data)
max = p;
}
insertp(t, remove(max)); //删除最大值节点,并插入最后
t = t->pred;
}
}
void List::insertsort() {
Node *p = first();
for(int i = 0; i < _size; i++){
inserts(search(p->data, i, p), p->data);
p = p->succ;
remove(p->pred);
}
}
Node *List::search(int const &e, int n, Node *p) {
do{
p = p->pred;
n--;
}while((n>-1)&&(p->data > e));
return p;
5. 测试
#include <iostream>
#include "Node.h"
#include "List.h"
using namespace std;
int main()
{
List l;
Node *first = l.insertAsFirst(1);
Node *sec = l.inserts(first, 3);
Node *third = l.insertp(sec, 5);
Node *fourth = l.insertAsLast(2);
l.remove(fourth);
fourth = l.insertAsLast(3);
l.deduplicate();
//l.selectsort();
l.insertsort();
Node *n = l.first();
for(int i=0; i<l.size(); i++) {
cout << n->data;
n = n->succ;
}
}
输出结果为:
135