首页 > 编程语言 >数组描述线性表(C++实现)

数组描述线性表(C++实现)

时间:2023-01-11 14:46:19浏览次数:52  
标签:theIndex const 线性表 iterator int arrayList C++ element 数组

线性表也称有序表,其每一个实例都是元素的一个有序集合

抽象类linearList

一个抽象类包含没有实现代码的成员函数,这样的成员函数称为纯虚函数,用数字0作为初始值来说明

template<class T>
class linearList {
public:
    virtual ~linearList() {};
    virtual bool empty() const = 0; // 是否为空
    virtual int size() const = 0; // 元素个数
    virtual T& get(int theIndex) const = 0; // 获取索引为theIndex的元素
    virtual int indexOf(const T &theElement) const = 0; // 返回元素第一次出现时的索引
    virtual void earse(int theIndex) = 0; // 删除索引为theIndex的元素
    virtual void insert(int theIndex,const T &theElement) = 0; // theElement插入线性表中索引为theIndex的位置上
    virtual void output(std::ostream& out) const = 0; // 输出流
};

此处定义了线性表的抽象类,及其一系列纯虚函数

数组描述

这里用一维数组来存储线性表元素

变长一维数组

定义如下函数可以改变数组的长度,首先建立一个具有新长度的数组,然后将数组a的元素复制到这个新数组,最后改变数组a的值,使其能够引用新数组

template<class T>
void changeLength1d(T* &a,int oldLength,int newLength) {
    if (newLength < 0) {
        throw illegalParameterValue("new length must be >= 0");
    }
    T* temp = new T[newLength];
    int number = min(oldLength,newLength);
    copy(a,a+number,temp);
    delete[] a;
    a = temp;
}

arrayList类

定义一个C++抽象类linearList的派生类arrayList,因为arrayList是一个具体类,所以它必须实现抽象类linearList的所有方法,同时还包含基类没有声明的方法

template<class T>
class arrayList : public linearList<T> {
public:
    arrayList(int initialCapacity = 10);
    arrayList(const arrayList<T>&);
    ~arrayList() { delete[] element; }

    bool empty() const { return listSize == 0; }
    int size() const { return listSize; }
    T& get(int theIndex) const;
    int indexOf(const T& theElement) const;
    void earse(int theIndex);
    void insert(int theIndex,const T& theElement);
    void output(std::ostream& out) const;
    int capacity() const { return arrayLength; }
protected:
    void checkIndex(int theIndex) const;
    T *element;
    int arrayLength;
    int listSize;
};

如下定义类构造函数和复制构造函数

template<class T>
arrayList<T>::arrayList(int initialCapacity) {
    if (initialCapacity < 1) {
        ostringstream s;
        s << "Initial capacity = " << initialCapacity << " Must be > 0";
        throw illegalParameterValue(s.str());
    }
    arrayLength = initialCapacity;
    element = new T[arrayLength];
    listSize = 0;
}

template<class T>
arrayList<T>::arrayList(const arrayList<T>& theList) {
    arrayLength = theList.arrayLength;
    listSize = theList.listSize;
    element = new T[arrayLength];
    copy(theList.element,theList.element+listSize,element);
}

类构造函数中,创建了一个长度为initialCapacity的数组,默认值为10,并初始化arrayLength和listSize

复制构造函数中是复制一个对象,当一个对象传值给一个函数,或者一个函数返回一个对象时,都要调用复制构造函数,利用了STL的copy函数

基本方法

如下定义了arrayList类基本的方法:

template<class T>
void arrayList<T>::checkIndex(int theIndex) const {
    if (theIndex < 0 || theIndex >= listSize) {
        ostringstream s;
        s << "index = " << theIndex << " size = " << listSize;
        throw illegalIndex(s.str());
    }
}

template<class T>
T& arrayList<T>::get(int theIndex) const {
    checkIndex(theIndex);
    return element[theIndex];
}

template<class T>
int arrayList<T>::indexOf(const T &theElement) const {
    int theIndex = (int) (find(element,element+listSize,theElement)-element);
    if (theIndex == listSize) {
        return -1;
    } else {
        return theIndex;
    }
}

checkIndex检查索引是否在有效范围内,get获取索引对应的元素,indexOf返回指定元素第一次出现的索引

删除元素

利用copy将索引从theIndex+1及其向后的元素向左移动一个位置,然后将listSize减1

template<class T>
void arrayList<T>::earse(int theIndex) {
    checkIndex(theIndex);
    copy(element+theIndex+1,element+listSize,element+theIndex);
    element[--listSize].~T();
}

插入元素

要把线性表中索引为theIndex的位置上插入一个新元素,首先将索引从theIndex到listSize-1的元素向右移动一个位置(调用copy_backward),然后将新元素插入指定位置:

template<class T>
void arrayList<T>::insert(int theIndex, const T &theElement) {
    if (theIndex < 0 || theIndex > listSize) {
        ostringstream s;
        s << "index = " << theIndex << " size = " << listSize;
        throw illegalParameterValue(s.str());
    }
    if (listSize == arrayLength) {
        changeLength1d(element,arrayLength,2*arrayLength);
        arrayLength *= 2;
    }
    copy_backward(element+theIndex,element+listSize,element+listSize+1);
    element[theIndex] = theElement;
    listSize++;
}

输出函数

定义输出函数(将线性表插入输出流),并重载流插入符<<

template<class T>
void arrayList<T>::output(ostream &out) const {
    copy(element,element+listSize,ostreambuf_iterator<T>(cout," "));
}

template <class T>
ostream& operator<<(ostream &out,const arrayList<T> &x) {
    x.output(out);
    return out;
}

迭代器

如下定义一个C++类iterator,是类arrayList的双向迭代器,这个迭代器是类arrayList的公有成员,此外为类arrayList增加两个公有的方法begin()和end()

class iterator;
iterator begin() { return iterator(element); }
iterator end() { return iterator(element+listSize); }

迭代器实现:

template<class T>
class iterator {
public:
    typedef std::bidirectional_iterator_tag iterator_category;
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef T *pointer;
    typedef T &reference;

    iterator(T *thePosition = 0) { position = thePosition; }
    T& operator*() const { return *position; }
    T* operator->() const { return &*position; }
    iterator& operator++() { ++position; return *this; }
    iterator& operator++(int) { iterator old = *this; ++position; return old; }
    iterator& operator--() { --position; return *this; }
    iterator& operator--(int) { iterator old = *this; --position; return old; }
    bool operator!=(const iterator right) const { return  position != right.position; }
    bool operator==(const iterator right) const { return position == right.position; }
protected:
    T *position;
};

标签:theIndex,const,线性表,iterator,int,arrayList,C++,element,数组
From: https://www.cnblogs.com/N3ptune/p/17043695.html

相关文章

  • C++_运算符重载
    operatoroverloadingCustomizestheC++operatorsforoperandsofuser-definedtypes.std::addressofstd::addressof模板函数定义在<memory>头文件中,用于获取类或......
  • 怎么在C++中调用Python?C++调用python封装接口实例解析!
    看到标题很多小伙伴会问:不是都说python是胶水语言,他调用什么什么语言封装的库来做一些什么事情吗?怎么小编你这反而变成被调用的对象了呢?没错,常规情况下一般都是以python语......
  • 【二分查找】LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置
    题目链接34.在排序数组中查找元素的第一个和最后一个位置思路转自:林小鹿的题解两套二分查找模板,分别用来查找左边界和右边界intbsearch_1(intl,intr){whil......
  • Python实例浅谈之三Python与C/C++相互调用
    一、问题     Python模块和C/C++的动态库间相互调用在实际的应用中会有所涉及,在此作一总结。二、Python调用C/C++1、Python调用C动态链接库       P......
  • C++_语言概览和资料
    C++C语言1969年-1973年完成,其出发点是为了编写Unix操作系统设计目标需求、背景和待解决问题 演化过程中,来自用户的反馈和语言实现者们积累的经验设计哲学:高效......
  • 浅析 C++ 调用 Python 模块
    作为一种胶水语言,Python 能够很容易地调用 C 、 C++ 等语言,也能够通过其他语言调用 Python 的模块。Python 提供了 C++ 库,使得开发者能很方便地从 C++ 程序中......
  • C++ STL摘记
    一、string类补充1.函数示例:(1)find和rfind函数,返回的是下标或者string::nposindex=ss.find(s1,pos,num)find从pos(包括)开始往右查找(num的作用待补充)index=s......
  • c++重要的概念部分
    1.const修饰指针#include<iostream>usingnamespacestd;intmain(){//1、const修饰指针指针常量inta=10;intb=20;int*constp=&a;//指针......
  • 后缀数组 II —— height 数组及其求法
    上集:后缀数组I——后缀排序记\(S_i\)表示以\(i\)为起点的后缀,\(sa_i\)表示对\(s\)进行后缀排序后排名为\(i\)的后缀,\(SA_i\)表示对\(s\)进行后缀排序......
  • C++ 编译依赖管理系统分析以及 srcdep 介绍
    C++编译依赖管理系统分析以及srcdep介绍如果用C++写一个中小型软件,有要用到很多第三方库的话,相信不少人会觉得比较麻烦。很多新兴的语言都有了统一的依赖管理系统和......