为什么学习数据结构
同样的问题,有的人写出来的程序效率高,有的人却用很复杂的方法解决。 学习数据结构能用最有效的方法解决绝大多数的问题。
基本概念和术语
1、 数据(Data) 计算机程序处理各种各样的数据,可以是数值数据,如整数、实数或复数;也可以是非数值数据,如字符、文字、图形、图像、声音等。
2、 数据元素(Data Element)和数据项(Data Item) 数据元素是数据的基本单位,在计算机程序中通常被作为一个整体进行考虑和处理。一个数据元素可由若干个数据项(Data Item)组成。数据项是不可分割的、含有独立意义的最小数据 单位,数据项有时也称为字段(Field)或域(Domain)。例如,一条学生记录就是一个数据元素。这条记录中的学生学号、姓名、性别、籍贯、出生年月、成绩等字段就是数据项。数据项分为两种,一种叫做初等项,如学生的性别、籍贯等,在处理时不能再进行分割;另一种叫做组合项,如学生的成绩,它可以再分为数学、物理、化学等更小的项。
3、 数据对象(Data Object) 数据对象是性质相同的数据元素的集合, 是数据的一个子集。例如,整数数据对象是{0,±1,±2,±3,…},字符数据对象是{a,b,c,…}。
4、 数据类型(Data Type) 数据类型是高级程序设计语言中的概念,是数据的取值范围和对数据进行操作的总和。数据类型规定了程序中对象的特性。程序中的每个变量、常量或表达式的结果都应该属于某种确定的数据类型。例如,C#语言中的字符串类型( String,经常写为 string)。一个 String 表示一个恒定不变的字符序列集合,所有的字符序列集合构成 String 的取值范围。我们可以对 String 进行求长度、复制、连接两个字符串等操作。
数据结构分类 (Data Structure)
数据结构是相互之间存在一种或多种特定关系的数据元素的集合。在任何问题中,数据元素之间都不是孤立的,而是存在着一定的关系,这种关系称为结构(Structure)。根据数据元素之间关系的不同特性,通常有 4 类基本数据结构:
(1) 集合(Set):如图 1.1(a)所示,该结构中的数据元素除了存在“同属于一个集合”的关系外,不存在任何其它关系。
(2) 线性结构(Linear Structure):如图 1.1(b)所示,该结构中的数据元素存在着一对一的关系。
(3) 树形结构(Tree Structure):如图 1.1(c)所示,该结构中的数据元素存在着一对多的关系。
(4) 图状结构(Graphic Structure):如图 1.1(d)所示,该结构中的数据元素存在着多对多的关系。
什么是算法
算法可以理解为有基本运算及规定的运算顺序所构成的完整的解题步骤。或者看成按照要求设计好的有限的确切的计算序列,并且这样的步骤和序列可以解决一类问题
算法和数据结构的关系
数据结构可以认为是数据在程序中的存储结构,和基本数据操作。 算法可以是认为解决问题的,算法是基于数据结构的。 数据结构是问题的核心,是算法的基础。
算法的评价标准
运行时间(Running Time)。 占用空间(Storage Space)。
有时需要牺牲空间来换取时间,有时需要牺牲时间来换取空间。
其他方面:正确性(Correctness)、可读性(Readability)、健壮性(Robustness)
什么是线性表
线性表是最简单、最基本、最常用的数据结构。线性表是线性结构的抽象(Abstract),线性结构的特点是结构中的数据元素之间存在一对一的线性关系。这种一对一的关系指的是数据元素之间的位置关系,即:
(1)除第一个位置的数据元素外,其它数据元素位置的前面都只有一个数据元素;
(2)除最后一个位置的数据元素外,其它数据元素位置的后面都只有一个元素。也就是说,数据元素是一个接一个的排列。因此,可以把线性表想象为一种数据元素序列的数据结构。 线性表就是位置有先后关系,一个接着一个排列的数据结构。
CLR中的线性表
c# 1.1 提供了一个非泛型接口IList接口,接口中的项是object,实现了IList解扣子的类有ArrayList,ListDictionary,StringCollection,StringDictionary.
c# 2.0 提供了泛型的IList<T>接口,实现了List<T>接口的类有List<T>
线性表的实现方式有下面几种
顺序表 单链表 双向链表 循环链表
顺序表
在计算机内,保存线性表最简单、最自然的方式,就是把表中的元素一个接一个地放进顺序的存储单元,这就是线性表的顺序存储(Sequence Storage)。线性表的顺序存储是指在内存中用一块地址连续的空间依次存放线性表的数据元素,用这种方式存储的线性表叫顺序表(Sequence List),如图所示。顺序表的特点是表中相邻的数据元素在内存中存储位置也相邻
代码实现
IListDS 线性表接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _001_线性表 {
interface IListDS<T>
{
//得到表数据个数
int GetLength();
//清空数据表
void Clear();
//表是否为空
bool IsEmpty();
//添加数据
void Add(T item);
//插入数据
void Insert(T item, int index);
//删除数据
T Delete(int index);
//通过下标 获取数据
T this[int index] { get; }
//通过下标 获取数据
T GetEle(int index);
//通过值 获取下标
int Locate(T value);
}
}
SeqList实现IListDS 线性表接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _001_线性表 {
/// <summary>
/// 顺序表实现方式
/// </summary>
/// <typeparam name="T"></typeparam>
class SeqList<T>:IListDS<T>
{
private T[] data;//用来存储数据
private int count = 0;//表示存了多少个数据
public SeqList(int size)//size就是最大容量
{
data = new T[size];
count = 0;
}
public SeqList():this(10)//默认构造函数 容量是10
{
}
/// <summary>
/// 取得数据的个数
/// </summary>
/// <returns></returns>
public int GetLength()
{
return count;
}
public void Clear()
{
count = 0;
}
public bool IsEmpty()
{
return count == 0;
}
public void Add(T item)
{
if (count == data.Length) //当前数组已经存满
{
Console.WriteLine("当前顺序表已经存满,不允许再存入");
}
else
{
data[count] = item;
count++;
}
}
public void Insert(T item, int index)
{
for (int i = count-1; i >=index; i--)
{
data[i + 1] = data[i];
}
data[index] = item;
count++;
}
public T Delete(int index)
{
T temp = data[index];
for (int i = index+1; i < count; i++)
{
data[i - 1] = data[i];// 把数据向前移动
}
count--;
return temp;
}
public T this[int index]
{
get { return GetEle(index); }
}
public T GetEle(int index)
{
if (index >= 0 && index <= count - 1) //索引存在
{
return data[index];
}
else
{
Console.WriteLine("索引不存在");
return default(T);
}
}
public int Locate(T value)
{
for (int i = 0; i < count; i++)
{
if (data[i].Equals(value))
{
return i;
}
}
return -1;
}
}
}
单链表
顺序表是用地址连续的存储单元顺序存储线性表中的各个数据元素,逻辑上相邻的数据元素在物理位置上也相邻。因此,在顺序表中查找任何一个位置上的数据元素非常方便,这是顺序存储的优点。但是,在对顺序表进行插入和删除时,需要通过移动数据元素来实现,影响了运行效率。线性表的另外一种存储结构——链式存储(Linked Storage),这样的线性表叫链表(Linked List)。链表不要求逻辑上相邻的数据元素在物理存储位置上也相邻,因此,在对链表进行插入和删除时不需要移动数据元素,但同时也失去了顺序表可随机存储的优点。
单链表的存储
链表是用一组任意的存储单元来存储线性表中的数据元素(这组存储单元可以是连续的,也可以是不连续的)。那么,怎么表示两个数据元素逻辑上的相邻关系呢?即如何表示数据元素之间的线性关系呢?为此,在存储数据元素时,除了存储数据元素本身的信息外