数据结构开发(3):线性表的顺序存储结构

0.目录

1.线性表的本质和操作

2.线性表的顺序存储结构

3.顺序存储结构的抽象实现和具体实现

  • 3.1 SeqList
  • 3.2 StaticList 和 DynamicList

4.顺序存储线性表的分析

  • 4.1 效率分析
  • 4.2 功能分析

5.小结

1.线性表的本质和操作

线性表 ( List ) 的表现形式:

  • 零个多个数据元素组成的集合
  • 数据元素在位置上是有序排列的
  • 数据元素的个数是有限的
  • 数据元素的类型必须相同

线性表 ( List ) 的抽象定义——线性表是具有相同类型的n(≥0)个数据元素的有限序列:
1250397-20181212212725823-1928882255.png

线性表 ( List ) 的性质:
1250397-20181212212746146-1102615029.png

线性表只是一个单纯的概念吗?如何在程序中描述和使用一个线性表?

线性表的一些常用操作:

  • 将元素插入线性表
  • 将元素从线性表中删除
  • 获取目标位置处元素的值
  • 设置目标位置处元素的值
  • 获取线性表的长度
  • 清空线性表

线性表在程序中表现为一种特殊的数据类型:
1250397-20181212212830286-969871232.png

(在StLib中实现List.h)

#ifndef LIST_H
#define LIST_H#include "Object.h"namespace StLib
{template <typename T>
class List : public Object
{
public:virtual bool insert(int i, const T& e) = 0;virtual bool remove(int i) = 0;virtual bool set(int i, const T& e) = 0;virtual bool get(int i, T& e) const = 0;virtual int length() const = 0;virtual void clear() = 0;
};}#endif // LIST_H

2.线性表的顺序存储结构

顺序存储的定义——线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表中的数据元素。
1250397-20181212212914712-52388629.png

设计思路——可以用一维数组来实现顺序存储结构:

  • 存储空间:T* m_array;
  • 当前长度:int m_length;

1250397-20181212212944937-2115115241.png

顺序存诸结构的元素获取操作:

  • 判断目标位置是否合法
  • 将目标位置作为数组下标获取元素

1250397-20181212213007780-454589713.png

顺序存储结构的元素插入操作:

  1. 判断目标位置是否合法
  2. 将目标位置之后的所有元素后移一个位置
  3. 将新元素插入目标位置
  4. 线性表长度加 1

顺序存储结构的元素插入示例:
1250397-20181212213037583-563361249.png

顺序存储结构的元素删除操作:

  1. 判断目标位置是否合法
  2. 将目标位置后的所有元素前移一个位置
  3. 线性表长度减 1

顺序存储结构的元素删除示例:
1250397-20181212213058820-799541133.png

3.顺序存储结构的抽象实现和具体实现

1250397-20181212221240681-1959137296.png

3.1 SeqList

本节目标:

  • 完成顺序存储结构线性表的抽象实现

SeqList设计要点:

  • 抽象类模板,存储空间的位置和大小由子类完成
  • 实现顺序存储结构线性表的关键操作(增,删,查,等)
  • 提供数组操作符,方便快速获取元素

1250397-20181212220608605-1294175795.png

(在StLib中实现SeqList.h)

#ifndef SEQLIST_H
#define SEQLIST_H#include "List.h"
#include "Exception.h"namespace StLib
{template <typename T>
class SeqList : public List<T>
{
protected:T* m_array;   // 顺序存储空间int m_length; // 当前线性表长度
public:bool insert(int i, const T& e){bool ret = ( (0 <= i) && (i <= m_length) );ret = ret && ( (m_length + 1) <= capacity() );if( ret ){for(int p=m_length-1; p>=i; p--){m_array[p+1] = m_array[p];}m_array[i] = e;m_length++;}return ret;}bool remove(int i){bool ret = ( (0 <= i) && (i <= m_length) );if( ret ){for(int p=i; p<m_length-1; p++){m_array[p] = m_array[p+1];}m_length--;}return ret;}bool set(int i, const T& e){bool ret = ( (0 <= i) && (i < m_length) );if( ret ){m_array[i] = e;}return ret;}bool get(int i, T& e) const{bool ret = ( (0 <= i) && (i < m_length) );if( ret ){e = m_array[i];}return ret;}int length() const{return m_length;}void clear(){m_length = 0;}// 顺序存储线性表的数组访问方式T& operator[] (int i){if( (0 <= i) && (i < m_length) ){return m_array[i];}else{THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");}}T operator[] (int i) const{return (const_cast<SeqList<T>&>(*this))[i];}// 顺序存储空间的容量virtual int capacity() const = 0;
};}#endif // SEQLIST_H

3.2 StaticList 和 DynamicList

本节目标:

  • 完成 StaticList 类的具体实现
  • 完成 DynamicList 类的具体实现

StaticList 设计要点:

  • 类模板
    1. 使用原生数组作为顺序存储空间
    2. 使用模板参数决定数组大小

1250397-20181212221011813-1675256042.png

(在StLib中实现StaticList.h)

#ifndef STATICLIST_H
#define STATICLIST_H#include "SeqList.h"namespace StLib
{template <typename T, int N>
class StaticList : public SeqList<T>
{
protected:T m_space[N];   // 顺序存储空间,N为模板参数
public:StaticList() // 指定父类成员的具体值{this->m_array = m_space;this->m_length = 0;}int capacity() const{return N;}
};}#endif // STATICLIST_H

main.cpp测试

#include <iostream>
#include "StaticList.h"
#include "Exception.h"using namespace std;
using namespace StLib;int main()
{StaticList<int, 5> l;for(int i=0; i<l.capacity(); i++){l.insert(0, i);}for(int i=0; i<l.capacity(); i++){cout << l[i] << endl;}l[0] *= l[0];for(int i=0; i<l.capacity(); i++){cout << l[i] << endl;}try{l[5] = 5;}catch(const Exception& e){cout << e.message() << endl;cout << e.location() << endl;}return 0;
}

运行结果为:

4
3
2
1
0
16
3
2
1
0
Parameter i is invalid ...
f:\allcode\qtcreator\datastructure\stlib\SeqList.h:97

DynamicList 设计要点:

  • 类模板
    1. 申请连续堆空间作为顺序存储空间
    2. 动态设置顺序存储空间的大小
    3. 保证重置顺序存储空间时的异常安全性
  • 函数异常安全的概念
    1. 不泄漏任何资源
    2. 不允许破坏数据
  • 函数异常安全的基本保证
    1. 如果异常被抛出
      1. 对象内的任何成员仍然能保持有效状态
      2. 没有数据的破坏及资源泄漏

1250397-20181212221129939-598542227.png

(在StLib中实现DynamicList.h)

#ifndef DYNAMICLIST_H
#define DYNAMICLIST_H#include "SeqList.h"namespace StLib
{template <typename T>
class DynamicList : public SeqList<T>
{
protected:T m_capacity; // 顺序存储空间的大小
public:DynamicList(int capacity) // 申请空间{this->m_array = new T[capacity];if( this->m_array != NULL ){this->m_length = 0;this->m_capacity = capacity;}else{THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create DynamicList object ...");}}int capacity() const{return m_capacity;}/* 重新设置顺序存储空间的大小 */void resize(int capacity){if( capacity != m_capacity ){T* array = new T[capacity];if( array != NULL ){int length = (this->m_length < capacity ? this->m_length : capacity);for(int i=0; i<length; i++){array[i] = this->m_array[i];}T* temp = this->m_array;this->m_array = array;this->m_length = length;this->m_capacity = capacity;delete[] temp;}else{THROW_EXCEPTION(NoEnoughMemoryException, "No memory to resize DynamicList object ...");}}}~DynamicList() // 归还空间{delete[] this->m_array;}
};}#endif // DYNAMICLIST_H

main.cpp测试

#include <iostream>
#include "DynamicList.h"
#include "Exception.h"using namespace std;
using namespace StLib;int main()
{DynamicList<int> l(5);for(int i=0; i<l.capacity(); i++){l.insert(0, i);}for(int i=0; i<l.length(); i++){cout << l[i] << endl;}cout << endl;l[0] *= l[0];for(int i=0; i<l.length(); i++){cout << l[i] << endl;}try{l[5] = 5;}catch(const Exception& e){cout << e.message() << endl;cout << e.location() << endl;l.resize(10);l.insert(5, 50);}l[5] = 5;for(int i=0; i<l.length(); i++){cout << l[i] << endl;}cout << endl;l.resize(3);for(int i=0; i<l.length(); i++){cout << l[i] << endl;}return 0;
}

运行结果为:

4
3
2
1
016
3
2
1
0
Parameter i is invalid ...
f:\allcode\qtcreator\datastructure\stlib\SeqList.h:97
16
3
2
1
0
516
3
2

问题:
是否可以将 DynamicList 作为 StaticList 的子类实现?
(不能将 DynamicList 作为 StaticList 的子类实现,反之也是不可以的,因为这两个类对于顺序存储空间的指定是截然不同没有任何关系的,因此它们两个的地位必然是位于同一层次的。)

4.顺序存储线性表的分析

4.1 效率分析

效率分析:
1250397-20181213140621776-452519882.png

问题:
长度相同的两个SeqList插入删除操作的平均耗时是否相同?
(insert操作最耗时的部分是for循环,究竟有多耗时取决于线性表里面存储的数据元素的类型是什么。如果存储的数据元素的类型是一个自定义的类,并且这个类还非常的庞大,那么插入操作就真的非常耗时了,因为涉及了对象之间的拷贝。)

4.2 功能分析

下面的代码正确吗?为什么?
1250397-20181213140640434-755433315.png
下面的代码正确吗?为什么?
1250397-20181213140648460-1084229020.png
功能分析:
对于容器类型的类,可以考虑禁用拷贝构造和赋值操作。
1250397-20181213140703169-1603513828.png

代码优化(List.h和SeqList.h):
优化List.h

#ifndef LIST_H
#define LIST_H#include "Object.h"namespace StLib
{template <typename T>
class List : public Object
{
protected:List(const List&);List& operator= (const List&);
public:List() { }virtual bool insert(const T& e) = 0;virtual bool insert(int i, const T& e) = 0;virtual bool remove(int i) = 0;virtual bool set(int i, const T& e) = 0;virtual bool get(int i, T& e) const = 0;virtual int length() const = 0;virtual void clear() = 0;
};}#endif // LIST_H

优化SeqList.h

#ifndef SEQLIST_H
#define SEQLIST_H#include "List.h"
#include "Exception.h"namespace StLib
{template <typename T>
class SeqList : public List<T>
{
protected:T* m_array;   // 顺序存储空间int m_length; // 当前线性表长度
public:bool insert(int i, const T& e){bool ret = ( (0 <= i) && (i <= m_length) );ret = ret && ( (m_length + 1) <= capacity() );if( ret ){for(int p=m_length-1; p>=i; p--){m_array[p+1] = m_array[p];}m_array[i] = e;m_length++;}return ret;}bool insert(const T& e){return insert(m_length, e);}bool remove(int i){bool ret = ( (0 <= i) && (i <= m_length) );if( ret ){for(int p=i; p<m_length-1; p++){m_array[p] = m_array[p+1];}m_length--;}return ret;}bool set(int i, const T& e){bool ret = ( (0 <= i) && (i < m_length) );if( ret ){m_array[i] = e;}return ret;}bool get(int i, T& e) const{bool ret = ( (0 <= i) && (i < m_length) );if( ret ){e = m_array[i];}return ret;}int length() const{return m_length;}void clear(){m_length = 0;}// 顺序存储线性表的数组访问方式T& operator[] (int i){if( (0 <= i) && (i < m_length) ){return m_array[i];}else{THROW_EXCEPTION(IndexOutOfBoundsException, "Parameter i is invalid ...");}}T operator[] (int i) const{return (const_cast<SeqList<T>&>(*this))[i];}// 顺序存储空间的容量virtual int capacity() const = 0;
};}#endif // SEQLIST_H

main.cpp测试

#include <iostream>
#include "DynamicList.h"using namespace std;
using namespace StLib;int main()
{DynamicList<int> l(5);for(int i=0; i<l.capacity(); i++){l.insert(i);}for(int i=0; i<l.length(); i++){cout << l[i] << endl;}return 0;
}

运行结果为:

0
1
2
3
4

下面的代码正确吗?为什么?
1250397-20181213140712180-505370125.png

问题分析:
顺序存储结构线性表提供了数组操作符重载,通过重载能够快捷方便的获取目标位置处的数据元素,在具体的使用形式上类似数组,但是由于本质不同,不能代替数组使用

5.小结

  • 线性表是数据元素的有序并且有限的集合
  • 线性表中的数据元素必须是类型相同的
  • 线性表可用于描述排队关系的问题
  • 线性表在程序中表现为一种特殊的数据类型
  • 线性表在C++中表现为一个抽象类
  • StaticList 通过模板参数定义顺序存储空间
  • DynamicList 通过动态内存申请定义顺序存诸空间
  • DynamicList 支持动态重置顺序存储空间的大小
  • Dynamiclist 中的 resize() 函数实现需要保证异常安全
  • 顺序存储线性表的插入和删除操作存在重大效率隐患
  • 线性表作为容器类,应该避免拷贝构造和拷贝赋值
  • 顺序存储线性表可能被当成数组误用
  • 工程开发中可以考虑使用数组类代替原生数组使用

转载于:https://www.cnblogs.com/PyLearn/p/10114009.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/484563.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小目标检测的一些问题,思路和方案

来源&#xff1a;机器学习研究组订阅机器学习正越来越多地进入我们的日常生活。从个人服务的广告和电影推荐&#xff0c;到自动驾驶汽车和自动送餐服务。几乎所有的现代自动化机器都能“看”世界&#xff0c;但跟我们不一样。为了像我们人类一样看到和识别每个物体&#xff0c;…

python-条件语句

#条件、循环和其他语句 #print:可以打印多个表达式&#xff0c;表达式之间用逗号隔开 print(a,"b",False)#参数并不构成一个元组 模块导入:import x :导入模块xfrom x import func &#xff1a;导入模块x的函数funcfrom x import func1,func2,... 导入模块…

一文读懂全球半导体市场

来源&#xff1a;深城物联作者&#xff1a;孙卓异&#xff0c;供职于赛迪顾问集成电路产业研究中心 半导体是当今信息技术产业高速发展的基础和原动力&#xff0c;已经高度渗透并融合到了经济、社会发展的各个领域&#xff0c;其技术水平和发展规模已经成为衡量一个国家产业竞争…

如何写好一份技术简历?

写简历的基本目的和策略 大部分情况下&#xff0c;写简历是找工作的第一步&#xff0c;考虑到第二步就是面试&#xff0c;那么简历就是敲门砖&#xff0c;为了让企业认识到你的价值&#xff0c;必须把自己的真实水平描述出来&#xff0c;展现出你有能力应对这份工作。甚至要体现…

这是我看过最全的工业机器人知识介绍 !

来源&#xff1a;产业智能官编者按工业机器人广泛使用在产业制造上&#xff0c;汽车制造、电器、食品等&#xff0c;能替代反复机器式操纵工作&#xff0c;是靠本身动力和控制才能来实现种种功用的一种机器。它能够承受人类指挥&#xff0c;也能够按照事先编排的程序运转。今天…

表白网站|程序猿的爱情记录网站模版|情侣日记网页

程序猿的爱情记录网站模版&#xff5c;情侣日记网页设计 介绍 我为我的女朋友制作了这个主页&#xff0c;目的是记录一些值得纪念的时刻。 如果需要&#xff0c;您可以复制和修改此模板作为送给女朋友或妻子的礼物。 Demo Click here to review the website! ❤️ https://…

python-字符串方法

#find方法&#xff1a;查找子串&#xff0c;返回子串所在位置的最左端索引&#xff0c;如果没有找到则返回-1 s"agsa" print(s.find("gs")) print(s.find("agsaa")) #可以指定匹配的起始点和结束点参数,包含第一个索引&#xff0c;不包含第二个索…

智慧食堂数据分析系统

智慧食堂数据分析系统&#xff5c;大数据分析&#xff5c;数据可视化 Demo Repo&#xff1a;https://github.com/sylvanding/AI-Restaurant-Data-Analysis项目演示&#xff08;模拟真实运行环境&#xff09;&#xff1a;http://analysis.sylvanding.online数据展示静态页面&am…

鸿蒙系统全面解析,诞生背景、技术细节生态圈一文看懂

编辑&#xff1a;智东西内参华为6月2日正式发布的鸿蒙系统无疑占据了最近热点话题的C位&#xff0c;虽然不全是赞美的声音&#xff0c;但这种努力打破美国垄断&#xff0c;挑战谷歌、苹果在移动操作系统上垄断地位的尝试必将成为中国科技史上的里程碑事件。本期的智能内参&…

python-字典

字典映射&#xff1a;通过名字来引用值&#xff1b;字典是python中唯一内建的映射类型&#xff1b;1)创建字典&#xff1a;字典有键-值对(项)组成&#xff0c;键和值之间通过冒号(:)隔开&#xff0c;项之间通过逗号(,)分割&#xff0c;整个字典由大括号括起来&#xff1b;空字典…

2021十大人工智能趋势

来源&#xff1a;雷锋网6月5日&#xff0c;以“交叉、融合、相生、共赢”为主题的2021全球人工智能技术大会&#xff08;GAITC 2021&#xff09;在杭州举行。会上&#xff0c;腾讯优图联合厦门大学人工智能研究院共同发布《2021十大人工智能趋势》&#xff08;以下简称“趋势报…

通过CTY、VTY、TTY访问网络设备[计网实践Cisco Packet Tracer]

实验一&#xff1a;接入网络设备 学习目标 CTY访问网络设备VTY访问网络设备TTY访问网络设备WEB访问网络设备 实验环境 Cisco Packet Tracer 6.0 原创文章&#xff0c;转载请注明出处&#xff1a;©️Sylvan Ding ❤️ 实验内容 CTY访问设备 CTY是指通过Console接口访…

细数二十世纪最伟大的10大算法

来源&#xff1a;深度学习于机器视觉编辑&#xff1a;nhyilin一、1946 蒙特卡洛方法[1946: John von Neumann, Stan Ulam, and Nick Metropolis, all at the Los Alamos Scientific Laboratory, cook up the Metropolis algorithm, also known as the Monte Carlo method.]1946…

python-元组

不可变序列&#xff1a;元组&#xff0c;字符串元组用两个圆括号()来表示;用逗号分隔一些值&#xff0c;则自动创建了元组a(1,2,3) print(a) print(())#空元组 #一个值的元组需在值后加一个逗号&#xff0c;与括号进行区分&#xff1b; b(1)#非元组 c(1,) print(b) print(c)#函…

MIT发布首个贝叶斯「数据清洗」机器人!8小时洗200万条数据

来源&#xff1a;GitHub和数据派THU编辑&#xff1a;王菁校对&#xff1a;林亦霖脏数据可以说是所有AI从业者、数据分析师、数据科学家的噩梦。好消息来了&#xff01;麻省理工学院的研究人员最近带来了一种全新的系统PClean&#xff0c;能够自动地清洗脏数据&#xff0c;如错误…

我的开源项目——Jerry

在日常工作中&#xff0c;经常会碰到一些问题&#xff0c;比如数字金额要写成千分位形式&#xff08;1234 -> 123,4.00&#xff09;、要写成汉字大写形式&#xff08;123 -> 壹佰贰拾叁圆&#xff09;&#xff0c;又比如要进行 cookie 读写操作&#xff0c;这些问题都比较…

python-列表和元组

python 数据结构 1.序列(包括元组、列表、字符串、buffer对象和xrange对象)序列中第一个元素的索引为0&#xff0c;第二个为1&#xff0c;依次类推序列的最后一个元素标记为-1&#xff0c;最后第二个为-2&#xff0c;依次类推 既可以向前计数&#xff0c;也可以向后计数2.列表和…

李德毅院士:希望智能驾驶成为我国继高铁之后又一张新名片

来源&#xff1a;汽车俱乐部Plus/ 导读 /5月19日&#xff0c;在WIC2021第五届世界智能大会的分论坛“智能交通峰会”上&#xff0c;中国工程院院士&#xff0c;欧亚科学院院士李德毅发表了主题演讲。以下是演讲实录。让我们掌声欢迎中国工程院院士&#xff0c;欧亚科学院院士&a…

windows下vagrant的安装使用

vagrant是简便虚拟机操作的一个软件&#xff0c;而使用虚拟机有几个好处&#xff1a; 1、为了开发环境与生产环境一致&#xff08;很多开发环境为windows而生产环境为linux&#xff09;&#xff0c;不至于出现在开发环境正常而移步到正式生产环境时出现各种问题&#xff0c;而v…

《2021全球脑科学发展报告》发布

来源&#xff1a;众诚智库编辑&#xff1a;蒲蒲近年来&#xff0c;以人工智能、量子信息、集成电路、生命健康、脑科学、生物育种、空天科技、深地深海等为代表的新一轮科技革命和产业变革深入发展&#xff0c;正在重构全球创新版图、重塑全球经济结构。在众多极具“颠覆性”的…