基于C++的ADT封装——双向链表、变长数组

双向链表

链表是一种通过指针将每个存储元素的结点链接在一起的链式线性数据结构。与普通数组相比,链表具有灵活的内存管理机制,在增删元素时可将时间复杂度优化至o(1),同时,链表由于其本身在插入元素时开辟空间的特点,可以较好地避免空间上的浪费。因此,链表更为广泛地应用于需要频繁增删元素的场景中。另外,链表在内存空间上的分布是离散的,并非是连续的。

一般地,链表分为单向链表双向链表循环链表。与单向链表相比,双向链表的每个结点拥有两个指针域和一个数据域,可以更加灵活地向前后两个方向进行遍历。以下则是双向链表基于C++的代码实现,供大家参考:

node.h

#ifndef _node_H
#define _node_H
#include <iostream>
typedef int ElemType;

class Node
{
public:
    ElemType e;
    Node *pre, *ne;
    Node(ElemType x);
    ~Node() = default;
};

#endif

node.cpp

#include "node.h"
#ifdef _node_H

Node::Node(ElemType x)
    :e(x), ne(nullptr), pre(nullptr){}

#endif

linkedlist.h

#ifndef _linkedlist_H
#define _linkedlist_H
#include <iostream>
#include "node.h"
typedef int ElemType;

class LinkedList
{
    size_t size;
    Node *head, *tail;

public:
    bool Empty() const;
    size_t Size() const;
    void HeadInsert(const ElemType x);
    void TailInsert(const ElemType x);
    void Insert(const ElemType x, size_t pos);
    void HeadRemove();
    void TailRemove();
    void Remove(size_t pos);
    void PrintList() const;
    void rPrintList() const;
    int Find(const ElemType x) const;
    int rFind(const ElemType x) const;
    ElemType GetElem(size_t pos) const;
    void clear();
    
    LinkedList();
    ~LinkedList();
};

#endif

linkedlist.cpp

#include "linkedlist.h"
#ifdef _linkedlist_H
#define INF 0x3f3f3f3f

//判断链表是否为空
bool LinkedList::Empty() const
{
    return !size;
}

//获取链表长度
size_t LinkedList::Size() const
{
    return size;
}

//头插一个元素
void LinkedList::HeadInsert(const ElemType x)
{
    Node *tmp = head->ne;
    head->ne = new Node(x);
    head->ne->pre = head;
    head->ne->ne = tmp;
    if(tmp)
    {
        tmp->pre = head->ne;
    }
    size++;
}

//尾插一个元素
void LinkedList::TailInsert(const ElemType x)
{
    tail->ne = new Node(x);
    tail->ne->pre = tail;
    tail = tail->ne;
    size++;
}

//向指定位置插入一个元素
void LinkedList::Insert(const ElemType x, size_t pos)
{
    if(pos >= size)
        return;
    Node *p = head->ne;
    while (pos-- && p)
        p = p->ne;
    Node *tmp = p->pre;
    tmp->ne = new Node(x);
    tmp->ne->pre = tmp;
    tmp->ne->ne = p;
    p->pre = tmp->ne;
    p = tmp = nullptr;
    size++;
}

//头删一个元素
void LinkedList::HeadRemove()
{
    if(Empty())
        return;
    Node *tmp = head->ne->ne;
    if(tmp)
    {
        delete head->ne;
        tmp->pre = head;
    }
    head->ne = tmp;
    tmp = nullptr;
    size--;
}

//尾删一个元素
void LinkedList::TailRemove()
{
    if (Empty())
        return;
    Node *tmp = tail;
    tail = tail->pre;
    delete tmp;
    tmp = nullptr;
    tail->ne = nullptr;
    size--;
}

//从指定位置删除一个元素
void LinkedList::Remove(size_t pos)
{
    if(!pos)
    {
        HeadRemove();
        return;
    }
    else if(pos == size - 1)
    {
        TailRemove();
        return;
    }
    else if (pos >= size)
        return;
    Node *p = head->ne;
    while (pos-- && p)
        p = p->ne;
    Node *t1 = p->pre, *t2 = p->ne;
    if (t1->e != INF)
        t1->ne = t2;
    if(t2)
        t2->pre = t1;
    delete p;
    size--;
}

//正向打印链表中元素
void LinkedList::PrintList() const
{
    for (Node *p = head->ne; p; p = p->ne)
    {
        std::cout << p->e << ' ';
    }
    std::cout << std::endl;
}

//逆向打印链表中元素
void LinkedList::rPrintList() const
{
    for (Node *p = tail; p->e != INF; p = p->pre)
    {
        std::cout << p->e << ' ';
    }
    std::cout << std::endl;
}

//正向查找第一个值为x的元素位置,不存在则返回-1
int LinkedList::Find(const ElemType x) const
{
    int pos = -1;
    for (Node *p = head->ne; p; p = p->ne)
    {
        pos++;
        if (p->e == x)
        {
            return pos;
        }
    }
    return -1;
}

//逆向查找第一个值为x的元素位置,不存在则返回-1
int LinkedList::rFind(const ElemType x) const
{
    int pos = size;
    for (Node *p = tail; p->e != INF; p = p->pre)
    {
        pos--;
        if (p->e == x)
        {
            return pos;
        }
    }
    return -1;
}

//获取指定位置上的元素
ElemType LinkedList::GetElem(size_t pos) const
{
    if (pos >= size)
    {
        return INF;
    }
    Node *p = head->ne;
    while(pos-- && p)
        p = p->ne;
    return p->e;
}

//清空链表元素
void LinkedList::clear()
{
    Node *p = tail;
    while (p->pre)
    {
        p = p->pre;
        delete p->ne;
    }
    delete p;
    head = nullptr;
    size = 0;
}

//构造函数
LinkedList::LinkedList()
    :size(0)
{
    head = new Node(INF);
    tail = head;
}

//析构函数
LinkedList::~LinkedList()
{
    Node *p = tail;
    while(p->pre)
    {
        p = p->pre;
        delete p->ne;
    }
    delete p;
}

#endif

变长数组

变长数组是一个可以根据数组中元素个数自动支配数组空间的数据结构,在普通数组的基础上增加了容量检测扩容机制,以达到更加灵活的空间分配。以下则是变长数组基于C++的代码实现,供大家参考:

array.h

#ifndef _array_H
#define _array_H
#include <iostream>
#include <malloc.h>
typedef int VElemType;

class Vector
{
    VElemType *arr;
    size_t size;
    size_t capacity;

    void Extend();

public:
    size_t Capacity() const;
    size_t Size() const;
    bool empty() const;
    void push_back(const VElemType& x);
    void pop_back();
    void _travel() const;
    void _rtravel() const;
    VElemType GetElem(const size_t pos) const;
    size_t count(const VElemType &x) const;
    size_t find(const VElemType &x) const;
    size_t rfind(const VElemType &x) const;
    void reverse();
    void clear();

    Vector(int maxn);
    ~Vector();
};

#endif

array.cpp

#include "array.h"
#ifdef _array_H

//获取容量
size_t Vector::Capacity() const
{
    return capacity;
}

//获取元素个数
size_t Vector::Size() const
{
    return size;
}

//判断是否为空
bool Vector::empty() const
{
    return size == 0;
}

//扩容
void Vector::Extend()
{
    size_t new_capacity = capacity << 1;
    VElemType *p = (VElemType*)realloc(arr, new_capacity * sizeof(VElemType));
    if(!p)
    {
        std::cout << "malloc error." << std::endl;
        return;
    }
    capacity = new_capacity;
    arr = p;
    p = nullptr;
}

//数组末压入元素
void Vector::push_back(const VElemType& x)
{
    if(size >= capacity)
        Extend();
    arr[size++] = x;
}

//弹出数组末元素
void Vector::pop_back()
{
    size--;
}

//遍历数组并打印
void Vector::_travel() const
{
    for (int i = 0; i < size; i++)
        std::cout << arr[i] << ' ';
    std::cout << std::endl;
}

//逆向遍历数组并打印
void Vector::_rtravel() const
{
    for (int i = size - 1; i >= 0; i--)
        std::cout << arr[i] << ' ';
    std::cout << std::endl;
}

//获取元素
VElemType Vector::GetElem(const size_t pos) const
{
    return arr[pos];
}

//修改元素
void Vector::SetElem(const size_t pos, const VElemType &x)
{
    arr[pos] = x;
}

//计数
size_t Vector::count(const VElemType& x) const
{
    size_t cnt = 0;
    for (int i = 0; i < size; i++)
    {
        if(arr[i] == x)
            cnt++;
    }
    return cnt;
}

//查找第一个值为x的元素
size_t Vector::find(const VElemType &x) const
{
    for (int i = 0; i < size; i++)
    {
        if(arr[i] == x)
            return i;
    }
    return -1;
}

//逆向查找第一个值为x的元素
size_t Vector::rfind(const VElemType &x) const
{
    for (int i = size - 1; i >= 0; i--)
    {
        if(arr[i] == x)
            return i;
    }
    return -1;
}

//将数组翻转
void Vector::reverse()
{
    int i = 0, j = size - 1;
    while (i < j)
    {
        int t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
        i++, j--;
    }
}

//清空数组元素
void Vector::clear()
{
    size = 0;
}

//构造函数:创建初始容量为maxn的变长数组
Vector::Vector(int maxn)
    :arr(nullptr), size(0), capacity(maxn)
{
    arr = (VElemType *)malloc(capacity * sizeof(VElemType));
}

//析构函数
Vector::~Vector()
{
    delete arr;
}

#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值