.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. 【ES6】数组的扩展——扩展运算符

    1.扩展运算符[三个点(...)将一个数组转为用逗号分隔的参数序列] 作用:用于函数调用 function add(x, y) { return x + y; } const numbers = [2 ...

  2. 《Java知识应用》Java发送邮件(QQ,163)

    1 准备 Jar包下载地址: 链接: https://pan.baidu.com/s/1kFZgWRR8yZaQH_baf6tzAg 提取码: x2e8 邮箱:授权码 2.案例: 通过QQ邮箱服务器 ...

  3. [UIApplication sharedApplication].keyWindow和[[UIApplication sharedApplication].delegate window]区别

    参考链接:https://www.cnblogs.com/henusyj-1314/p/11643189.html 结论1.在获取到window时最好使用[[UIApplication sharedA ...

  4. 安卓AlertDialog四种对话框的最科学编写用法

    首先我们上图: xml的代码如下,用于编写按钮: <?xml version="1.0" encoding="utf-8"?> <Linear ...

  5. Android 项目优化(三):MultiDex 优化

    在整理MultiDex优化之前,先了解一下Apk的编译流程,这样有助于后面针对MultiDex优化. 一.Apk 编译流程 Android Studio 按下编译按钮后发生了什么? 1. 打包资源文件 ...

  6. MSSQL - 最佳实践 - 使用SSL加密连接

    MSSQL - 最佳实践 - 使用SSL加密连接 author: 风移 摘要 在SQL Server安全系列专题月报分享中,往期我们已经陆续分享了:如何使用对称密钥实现SQL Server列加密技术. ...

  7. Spring注解之@Autowired

    前言 说起Spring的@Autowired注解,想必大家已经熟悉的不能再熟悉了.本文就针对此最常用的注解,梳理一下它的功能和原理,争取从源码的角度将此注解讲通,如有写的不准确的地方,欢迎各位园友拍砖 ...

  8. Spring中常见的设计模式——委派模式

    一.委派模式的定义及应用场景 委派模式(Delegate Pattern)的基本作用是负责任务的调用和分配,跟代理模式很像,可以看做特殊情况下的静态的全权代理,但是代理模式注重过程,而委派模式注重结果 ...

  9. vc6.0 绿色版 下载地址

    最新版的vs2019已经完全不支持生成运行在xp下的应用程序 每次在xp下测试,都需要配置好vc6.0,但乱七八糟的太多了,给出地址,绿色版可用 http://www.downcc.com/soft/ ...

  10. python中time.strftime不支持中文,报错UnicodeEncodeError: 'locale' codec can't encode character '\u5e74' in position 2: encoding error

    使用time.strftime将 "2020-10-10 10:10:10" 转化为  2020年10月10日10时10分10 报错: import time timestr=&q ...