.NET Core 数据结构与算法 1-1

本节内容为顺序表

简介

线性表是简单、基本、常用的数据结构。线性表是线性结构的抽象 (Abstract),线性结构的特点是结构中的数据元素之间存在一对一的线性关系。这 种一对一的关系指的是数据元素之间的位置关系,即:

  • 除第一个位置的数据元素外,其它数据元素位置的前面都只有一个数据元素;
  • 除后一个位置的数据元素外,其它数据元素位置的后面都只有一个元素。也就是说,数据元素是 一个接一个的排列。因此,可以把线性表想象为一种数据元素序列的数据结构。

本节我们对线性表中的顺序表进行一个讲解。

保存线性表简单、自然的方式,就是把表中的元素一个接一个地放进顺序的存储单元,这就是线性表的顺序存储(Sequence Storage)。线性表的顺序存储是指在内存中用一块地址连续的空间依次存放线性表的数据元素, 用这种方式存储的线性表叫顺序表(Sequence List)。说的明确一些也就是说,顺序表就是我们所接触过的数组。

线性表接口IListDS<T>

我们首先对我们会涉及到的函数进行一次封装,打包进线性表的接口中

interface IListDS<T>
{
int GetLength();//求长度,我们也可以通过属性进行操作
void Clear();//清空操作
bool IsEmpty();//判断线性表是否为空
void Append(T item);//向后追加操作
void Insert(T item, int i);//插入操作
T Delete(int i);//删除操作
T GetElem(int i);//取表元
}

对于C语言,我们很多需要使用函数进行操作,但是在C#中,我们有索引器,属性等一系列语法糖,因此我们在后面操作的时候会把这些都展示给你们看。

事实上在我们之前的C#初级教程中的综合练习,就是关于我们的线性表操作,你可以返回去参考你的代码。

顺序表类SeqList<T>

为了方便起见,我们在此处不做可变长度的线性表,如果需要使用可变长度,这里有那么一种思路供读者思考:定义一个字段为容量(Cap),一个为长度(len),长度是以及存储的空间大小,容量是总空间,如果长度和容量相等的时候,证明我们的表已经满了,那么就向后追加空的数组即可。

不过在这里我们不讨论这种,我们仅仅使用定长的就足够展示了

class SeqList<T>:IListDS<T>
{
private int length;//长度
private int size;
private int lastIndex;//最后一个元素的索引
private T[] data;
public int Length{get{return lastIndex+1;}}
//初始化
public SeqList<T>(int size)
{
this.data = new T[size];
this.lastIndex = -1;
this.size = size;
}
//清除内部元素
public void Clear()
{
this.data = new T[this.size];
lastIndex = -1;
}
//判断是否为空,只需要判断最后一个元素的索引是否为-1即可
public bool IsEmpty()
{
return lastIndex==-1?true:false;
}
//获取长度
public int GetLength()
{
return lastIndex + 1;
}
//是否已满
public bool IsFull()
{
return size == lastIndex+1?true:false;
}
//向后追加
public void Append(T item)
{
//只需要判断是否已满即可
if(!IsFull())
{
data[lastIndex++] = item;
}
else
{
Console.WriteLine("It is Full");
}
}
//在指定位置插入,index指代位置而不是索引
public void Insert(T item,int index)
{
//首先判断是否已满
if(IsFull())
{
Console.WriteLine("It is Full");
return;
}
if(index<1||index>lastIndex+2)
{
Console.WriteLine("error");
return;
}
//最后一位插入
if (i == last +2)
{
data[i-1] = item;
}
else
{
//元素移动
for (int j = lastIndex; j>= i-1; --j)
{
data[j + 1] = data[j];
}
data[i-1] = item;
}
lastIndex++;
}
public T Delete(int i)
{
T tmp = default(T); //判断表是否为空
if (IsEmpty())
{
Console.WriteLine("List is empty"); return tmp;
} //判断删除的位置是否正确
// i小于1表示删除第1个位置之前的元素,
// i大于last+1表示删除后一个元素后面的第1个位置的元素。
if (i < 1 || i > lastIndex+1)
{
Console.WriteLine( "Position is error!");return tmp;
}
//删除的是后一个元素
if (i == lastIndex+1)
{
tmp = data[last--];
}
//删除的不是后一个元素
else
{
//元素移动
tmp = data[i-1];
for (int j = i; j <= lastIndex; ++j)
{
data[j] = data[j + 1];
}
}
//修改表长
--lastIndex;
return tmp;
}
public T GetElem(int i)
{
if(i<1||lastIndex==-1)
{
Console.WriteLine("error");
return;
}
return this.data[i-1];
}
}

在上述代码中,我们分析一下删除和插入的操作

算法的时间复杂度分析:顺序表上的删除操作与插入操作一样,时间主要消 耗在数据的移动上在第i个位置删除一个元素,从ai+1到an都要向前移动一个位置,共需要移动n-i个元素,而i的取值范围为 1≤i≤n,当i等于 1 时,需要移动 的元素个数多,为n-1 个;当i为n时,不需要移动元素。设在第i个位置做删除 的概率为pi,则平均移动数据元素的次数为(n-1)/2。这说明在顺序表上做删除操 作平均需要移动表中一半的数据元素,所以,删除操作的时间复杂度为O(n)。

一些额外操作

我们以倒转为例,事实上我们倒转的时候,只需要将第一个和最后一个,第二个和倒数第二个以此类推进行交换即可

public void ReversSeqList(SeqList<int> L)
{
int tmp = 0;
int len = L.GetLength();
for (int i = 0; i<= len/2; ++i)
{
tmp = L[i];
L[i] = L[len - i];
L[len - i] = tmp;
}
}

各位可以尝试一下生成不含重复值顺序表和合并顺序表并有序的排列算法,这里给出一些思路。

  • 去重:先把顺序表 La 的第 1 个元素赋给顺序表 Lb,然后从顺序表 La 的第 2 个元素起,每一个元素与顺序表 Lb 中的每一个元素进行比较,如果不相 同,则把该元素附加到顺序表 Lb 的末尾。
  • 合并排序:依次扫描 La 和 Lb 的数据元素,比较 La 和 Lb 当前数据元素的 值,将较小值的数据元素赋给 Lc,如此直到一个顺序表被扫描完,然后将未完 的那个顺序表中余下的数据元素赋给 Lc 即可。Lc 的容量要能够容纳 La 和 Lb 两个表相加的长度。

Github

BiliBili主页

WarrenRyan's Blog

博客园

.NET Core 数据结构与算法 1-1的更多相关文章

  1. 《数据结构与算法之美》 <01>复杂度分析(上):如何分析、统计算法的执行效率和资源消耗?

    我们都知道,数据结构和算法本身解决的是“快”和“省”的问题,即如何让代码运行得更快,如何让代码更省存储空间.所以,执行效率是算法一个非常重要的考量指标. 那如何来衡量你编写的算法代码的执行效率呢?这里 ...

  2. 数据结构和算法(Golang实现)(25)排序算法-快速排序

    快速排序 快速排序是一种分治策略的排序算法,是由英国计算机科学家Tony Hoare发明的, 该算法被发布在1961年的Communications of the ACM 国际计算机学会月刊. 注:A ...

  3. [GitHub] 75+的 C# 数据结构和算法实现

    C#中标准数据结构和算法的即插即用类库项目 GitHub:https://github.com/aalhour/C-Sharp-Algorithms Watch: 307 Star: 3.4k For ...

  4. 开启基本数据结构和算法之路--初识Graphviz

    在我的Linux刀耕开荒阶段,就想开始重拾C,利用C实现常用的基本数据结构和算法,而数据结构和算法的掌握的熟练程度正是程序的初学者与职业程序员的分水岭. 那么怎么开启这一段历程呢? 按照软件工程的思想 ...

  5. 【转】MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  6. [转]MySQL索引背后的数据结构及算法原理

    摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BT ...

  7. MySQL索引背后的数据结构及算法原理【转】

    本文来自:张洋的MySQL索引背后的数据结构及算法原理 摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持 ...

  8. 数据结构与算法JavaScript (一) 栈

    序 数据结构与算法JavaScript这本书算是讲解得比较浅显的,优点就是用javascript语言把常用的数据结构给描述了下,书中很多例子来源于常见的一些面试题目,算是与时俱进,业余看了下就顺便记录 ...

  9. 数据结构与算法 Big O 备忘录与现实

    不论今天的计算机技术变化,新技术的出现,所有都是来自数据结构与算法基础.我们需要温故而知新.        算法.架构.策略.机器学习之间的关系.在过往和技术人员交流时,很多人对算法和架构之间的关系感 ...

随机推荐

  1. MySQL高级查询之索引创建、删除、增加、修改、慢sql、explain解释sql

    day04数据库 昨日知识点回顾 1.单表操作 1.单表的操作 条件查询的优先级别: where > group by >having > order by > limit; ...

  2. 解决苹果mac远程桌面无VDI客户端

    解决苹果mac远程桌面云aDesk无VDI客户端 因集团办公工作需要使用桌面云aDesk 在深信服官网并未有mac 的VDI Client客户端 mac电脑可通过Google浏览器访问VDI的服务器地 ...

  3. AOP框架Dora.Interception 3.0 [3]: 拦截器设计

    对于所有的AOP框架来说,多个拦截器最终会应用到某个方法上.这些拦截器按照指定的顺序构成一个管道,管道的另一端就是针对目标方法的调用.从设计角度来将,拦截器和中间件本质是一样的,那么我们可以按照类似的 ...

  4. Mbp,一个用于学习.net core的开发框架

    Mbp(https://github.com/mbpframework/Mbp)是一个.net core 3的企业级web开发框架,是我个人用于学习.net core而发起的一个开源项目.这个借鉴了国 ...

  5. NetCore MemoryCache使用

    引用类库 1.Install-Package Microsoft.Extensions.Caching.Memory MemoryCacheOptions 缓存配置 1.ExpirationScanF ...

  6. 敏捷:你能区分DevOps中的“集成、部署、交付、上线、发布”吗?

    在DevOps中,你可能经常会听到类似这样的一些话: 功能还没集成进来. 功能还没部署上去. 功能还没交付. 功能还没上线. 功能还没发布. 请问,以上“集成”.“部署”. “交付”.“上线”.“发布 ...

  7. MySQL Event历史记录

    需求 SQL Server的作业历史(Job)记录是保存在msdb库中的,很方便就查询相关的Job定义,计划和历史记录,而MySQL的event却没有历史记录.为方便查看event是否正常执行以及执行 ...

  8. 基于V6的中移动物联测试例子,当前测试还挺稳定

    下载: 链接:https://pan.baidu.com/s/1Gz8mEffDGXNSK8lIsAIUEg   提取码:2sur 测试步骤看此贴,跟V7开发板是一样的: 基于H7的中移动物联例子以及 ...

  9. JavaBean动态添加删除属性

    1.cglib BeanGenerator beanGenerator = new BeanGenerator(); beanGenerator.addProperty("id", ...

  10. C# 多线程、异步、同步之间的联系与区别

    C# 多线程.异步.同步之间的联系与区别 假设这样一个例子: 我想炒五样菜,但是只有两个炉子可以用,只能同时炒两样. 炉子就是线程,那同步跟异步怎么解释比较好? 同时炒是不是算异步? 如果是的话,那什 ...