数据结构之双向链表的接口与实现(c++版)

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值