C++数据结构:线性顺序表(数组)

C++数据结构

线性顺序表(数组)
线性顺序表(链表)
Python风格双向链表的实现
散列表简单实现(hash表)
栈和队列的应用
二叉树之一(数组存储)
二叉树之二(二叉搜索树)
二叉树之三(二叉搜索树扩展)
图结构入门



前言

将一个线性表存储到计算机中,把线性表的结点按逻辑顺序依次存放到一组地址连续的存储单元里,用这种方法存储的线性表称为顺序表。C++中数组、vector、list就是典型的顺序表,其中list是以链表实现的,本文主要以仿写一个数组实现的顺序表,进而更深入了解顺序表。


提示:以下是本篇文章正文内容,下面案例可供参考

一、vector简介

vector是一种动态数组,它可以根据需要自动调整大小,存储连续的元素。vector的优点是可以快速地随机访问任意元素,而不需要遍历。缺点是在中间或开头插入或删除元素时,需要移动后面的元素,效率较低。

vector在计算机中的存储方式与普通数组类似,都是采用连续的内存空间来存放元素。但是,vector有一个特殊的成员变量capacity,表示vector分配的内存空间的大小。当vector的元素个数超过capacity时,vector会自动分配更大的内存空间,并将原来的元素复制到新的空间中,然后释放原来的空间。

在这里插入图片描述
上图很形象的表示了,数组在计算机中的存储方式。其中存储地址 b 表示了数组的起始内存地址,实际情况上它的值类似于 0x00000000000b,一般在存储 int 数据情况下每个 int整数占4个字节,那么第二个地址就是 b+4,所以 b+d 就是 0x00000000000f ,以此类推。实际上我们在使用数组时,变量所存储的即是内存块的起始 b 的地址,直接 cout 数组的变量名即可得到这个地址。用C++语言描述:这就是一个指针。

笔者只是为了更好的了解数组,没必要也不可能完整的实现 vector 的功能。以下仅实现插入、删除、size()、begin()、end()等方法的部分简单功能。

二、泛型编程自定义数组结构

这里采用了泛型编程的方法,使得代码更有通用性。简单来说就是这个 Arrary 类可以用于存储 int、char、或string、bool 等各种C++数据类型,和STL中的各种容器一样。

1、定义类

#include <iostream>

using namespace std;
template <typename T> class Array{
    private:
        static const int default_size = 64;
        T *elems;
        int max_size;
        int len;

    public:
        Array(int size=default_size){
            if(size){
                max_size = size;
                len = 0;
                elems = new T[max_size];
                for (int i=0; i<max_size; ++i)
                    elems[i] = (T)NULL;
            }
        }

        ~Array(){
            delete[] elems;
        }

这里只是为了学习,所以定义了最大元素数量为64个,vector是可以自动调整这个值的。私有域中定义了各个变量、和函数名。构造函数Array初始化各值、分配了最大的内存空间。并写了析构函数用以释放内存。

2、删除、读取元素和首尾指针

  • delete_elem()方法用于按下标删除元素、判断是否超界后直接将后面的元素前移就行了。因为用了元素数量为界。
  • get_elem() 方法用于按下标取元素值,实现逻辑与删除基本类似。
  • begins()、 ends() 简单的返回了首尾元素的地址,其也是可以用于迭代循环的。可以参考以下迭代循环用法:
    for (auto it=arr.begins();it!=arr.ends();it++) { cout << *it <<endl; }
bool delete_elem(int loca){
            if (loca >= len || loca < 0){
                 return false;
            }else{
                for (int i=loca; i<len; ++i){
                    elems[i] = elems[i+1];
                }
                len--;
                return true;
            }
        }

        T get_elem(int loca){
            if (loca >= len || loca < 0){
                return (T)NULL;
            }else{
                return elems[loca];
            }
        }

        T* begins(){
            return elems;
        }

        T* ends(){
            return elems + len;
        }

3、修改元素、获取元素数量、和插入

代码都相当的简单,逻辑也与其它几个函数基本一致。就不再单独介绍了,有兴趣的可以自己解读一下。

        bool change_elem(int loca, T newdata){
            if (loca >= len || loca <0){
                return false;
            }else{
                elems[loca] = newdata;
                return true;
            }
        }

        int get_len(){
            return len;
        }

        bool insert_elem(T data){
            int curr_index = len;
            if (len >= max_size){
                return false;
            }else{
                elems[curr_index] = data;
                len++;
                return true;
            }
        }
}

以上代码虽然没有什么实用性,但相信对于了解数组的数据结构还是有一定帮助的,代码均是经过测试的。使用cout << "begins is " << arr.begins() << endl;输出结果是:begins is 0x7fece55053e0 与预期一致。不要深究以上代码中的变量及函数名称,主要为了避免与STL中的模板同名,不好区分才取这些奇怪名字的,事实上只要类名不同,方法名一样是可以的。


总结

数组实现顺序表是很简单的,因为各成员功能函数均很容易实现,只是给数组用类再包装一下,实现几个有用的方法而已。虽然它并没有多大的实用性,但有兴趣的看官也可以试试,还可以给它加上类似python的排序方法,C++ STL中algorithm排序的参数太多。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无证的攻城狮

如本文对您有用,大爷给打个赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值