线性表
线性表是线性结构的抽象,线性结构的特点是结构中的数据元素之间存在一对一的线性关系。这种一对一的关系指的是数据元素之间的位置关系。即
- 除第一个位置的数据元素外,其他数据元素位置的前面都只有一个数据元素;
- 除最后一个位置的数据元素外,其他数据元素位置后面都只有一个元素。
也就是说,数据元素是一个接一个的排列。
定义
线性表是由n(n>=0)个相同类型的数据元素构成的有限序列。
线性表的操作接口
以c#做为编写语言,并且使用int型来作为数据元素的数据类型;
//线性表接口:约定线性表的位置以0开始
public interface IList_Int_DS
{
/// <summary>
/// 返回线性表中所有数据元素的个数
/// </summary>
/// <returns>表的长度</returns>
int GetLength();
/// <summary>
/// 清空线性表
/// </summary>
void Clear();
/// <summary>
/// 线性表是否为空
/// </summary>
/// <returns></returns>
bool IsEmpty();
/// <summary>
/// 附加,在线性表末尾添加新元素
/// </summary>
/// <param name="elem">元素</param>
void Append(int elem);
/// <summary>
/// 插入
/// </summary>
/// <param name="key">插入的位置</param>
/// <param name="value">插入的值</param>
void Insert(int key, int value);
/// <summary>
/// 移除(从表末)
/// </summary>
void Remove();
/// <summary>
/// 删除
/// </summary>
/// <param name="key">删除的位置</param>
/// <returns>返回删除后的数据元素</returns>
int Delete(int key);
/// <summary>
/// 获取值
/// </summary>
/// <param name="key">值所处的位置</param>
/// <returns>返回线性表中第key的元素</returns>
int GetElem(int key);
/// <summary>
/// 按值查找
/// </summary>
/// <param name="value">查找的值</param>
/// <returns>返回在线性表中首次出现的值为value的元素,否则未找到该元素,返回一个特殊值表示查找失败(-1)</returns>
int Locate(int value);
}
顺序表
作为线性表的一种存储结构。
顺序表的定义
把表中的元素一个接一个地放进顺序的存储单元,这就是线性表的顺序存储(Sequence Storage)。
线性表的顺序存储是指在内存中用一块地址连续的空间依次存放线性表的数据元素,用这种方式存储的线性表叫顺序表(Sequence List)。
顺序表的特点是表中相邻的数据元素在内存中存储的位置也相邻。
实现
C#中数组在内存中占用的存储空间就是一组连续的存储区域,因此,数组具有随机存取的特点。所以,数组天生具有表示顺序表的数据存储区域的特性。
//顺序表
public class SeqList_Int_DS : IList_Int_DS
{
int[] data;//以数组来存储线性表
int last;//最后一个数据元素位置
int maxsize;//顺序表最大容量
public SeqList_Int_DS(int size)
{
data = new int[size];
maxsize = size;
last = -1;//设定线性表为空为置该值为-1
}
//扩充线性表
public void BrodaenList(int brodaenNum)
{
int[] copy = new int[maxsize + brodaenNum];
data.CopyTo(copy, 0);
data = null;
GC.Collect();
data = copy;
maxsize += brodaenNum;
}
//索引器
public int this[int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
public void ShowTostring()
{
Debug.Log(ToString());
}
public new string ToString()
{
StringBuilder builder = new StringBuilder();
for (int i = 0; i < last + 1; i++)
{
builder.Append(data[i]);
builder.Append(" ");
}
//foreach (var item in data)
//{
// builder.Append(item);
//}
return builder.ToString();
}
public bool IsEmpty()
{
if (last == -1)
return true;
return false;
}
/// <summary>
/// 线性表是否已满
/// </summary>
/// <returns></returns>
private bool IsFull()
{
if (last == maxsize - 1)
return true;
return false;
}
public void Append(int elem)
{
if (IsFull())
{
Debug.LogWarning("线性表已经满了,插入失败!");//增加修改线性表长度TODO
return;
}
last++;
data[last] = elem;
}
public void Insert(int key, int value, bool isFill = true)
{
if (IsFull())
{
Debug.LogWarning("线性表已经满了,插入失败!");//增加修改线性表长度TODO
return;
}
if (key < 0)
{
Debug.LogWarning("插入位置不合法,出现意外的位置,出现负值!");
return;
}
if (key > maxsize - 1)
{
Debug.LogWarning("插入位置不合法,超过线性表的最大范围!");
return;
}
if (key > last + 1)
{
if (!isFill)
{
Debug.LogWarning("插入位置不合法,超过当前线性表的最大位置+1(last + 1),若要填充中间未含有参数位置请使用Insert(key,value,isFill)使isFill为true");
}
else
{
for (int i = last + 1; i < key; i++)
{
data[i] = 0;
last++;
}
data[key] = value;
last++;
}
return;
}
if (key == last + 1)
{
Append(value);
}
else
{
#if Way_1 //从前往后移动
last++;
int tmp_f, tmp_l;
tmp_l = data[key];
data[key] = value;
tmp_f = tmp_l;
for (int i = key; i < last - 1; i++)
{
tmp_l = data[i + 1];
data[i + 1] = tmp_f;
tmp_f = tmp_l;
}
data[last] = tmp_f;
#else //从后往前移动
last++;
for (int i = last; i > key; i--)
{
data[i] = data[i - 1];
}
data[key] = value;
#endif
}
}
public void Insert(int key, int value)
{
}
public void Clear()
{
if (!IsEmpty())
last = -1;
}
public int Delete(int key)
{
if (IsEmpty())
{
Debug.LogWarning("顺序表为空,删除错误!");
return -1;
}
if (key < 0 || key > last)
{
Debug.LogWarning("传入的位置键有误,删除失败!");
return -1;
}
int tmp = 0;
if (key == last)
{
tmp = data[last];
}
else
{
tmp = data[key];
for (int i = key; i < last; i++)
{
data[i] = data[i + 1];
}
}
last--;
return tmp;
}
public void Remove()
{
if (IsEmpty())
{
Debug.LogWarning("表为空,移除失败!");
return;
}
last--;
}
public int GetElem(int key)
{
if (key > last || key < 0)
{
Debug.LogWarning("传入位置键有误!");
return -1;
}
return data[key];
}
public int Locate(int value)
{
for (int i = 0; i < last + 1; i++)
{
if (data[i] == value)
return i;
}
Debug.Log("顺序表中没有与传入值匹配的元素");
return -1;
}
public int GetLength()
{
return last + 1;
}
}
尾
- 顺序表是用地址连续的存储单元顺序存储线性表中的各个数据元素,逻辑上的数据元素在物理位置上也相邻。因此,在顺序表中查找任何一个位置上的数据元素非常方便,这是顺序存储的优点;
- 但是,在对顺序表进行插入和删除时,需要通过移动数据元素来实现,影响了运行效率。