线性表的定义
线性表(List):零个或多个数据元素的有限序对。
强调:
1. 线性表是有限的。
2. 元素之间是有顺序的。
3. 若存在多个元素,则第一个元素无前驱,最后一个元素无后继。
4. 其他每个元素都有且只有一个前驱和后继。
数学语言定义
若线性表记为(a1,…ai-1,ai,ai+1,…,an),则表中ai-1领先于ai,ai领先于ai+1,称ai-1是ai的直接前驱元素,ai+1是ai的直接后继元素。当i=1,2,…,n-1时,ai有且仅有一个直接后继,当i=2,3,…n时,ai有且仅有一个直接前驱。
线性表元素的个数n(n>=0)定义为线性表的长度,当n=0时,称为空表。
线性表的顺序存储结构
顺序存储的定义
线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。
a1 |
a2 |
…… |
ai-1 |
ai |
…… |
an |
顺序表至少需要3个属性
1. 存储空间:一个一维数组,它的存储位置就是存储空间的存储位置。
2. 线性表的最大存储容量:数组长度MaxSize。
3. 线性表的当前长度:length。
注意
这里有2个概念:“数组的长度”和“线性表的长度“需要区分下
数组的长度是存放线性表的存储空间的长度,存储分配以后这个量是不变的。
线性表的长度是线性表中数据元素的个数,随着线性表的插入和删除等操作的进行,这个量是变化的。
地址的计算方法
存储器中每个存储单元都有自己的编号,这个编号称为地址。
假设线性表的每个元素占用c个存储单元,那么线性表中第i+1个数据元素的存储位置和i个数据元素的存储位置满足下列关系(LOC表示获得存储位置的函数)。
LOC(ai+1)=LOC(ai)+c;
LOC(ai)=LOC(a1)+(i-1)*c;
--------------------------代码------------------------------
class Program
{
static void Main(string[] args)
{
try
{
SeqList<string> list = newSeqList<string>(5);
Console.WriteLine("IsEmpty={0}", list.IsEmpty());
Console.WriteLine("插入3个元素");
list[0] = "a";
list[1] = "b";
list[2] = "c";
Console.WriteLine("IsEmpty={0}", list.IsEmpty());
ShowList(list);
Console.WriteLine("----------------------------------");
Console.WriteLine("删除第2个元素");
string str = list.Delete(2);
Console.WriteLine("被删除的元素是{0}", str);
ShowList(list);
Console.WriteLine("----------------------------------");
Console.WriteLine("附加一个元素d");
list.Append("d");
Console.WriteLine("list长度={0} list最后一个元素索引是={1}", list.GetLength(), list.Last);
ShowList(list);
Console.WriteLine("----------------------------------");
Console.WriteLine("删除第一个元素a,然后在第2个位置插入e");
list.Delete(1);
list.Insert("e", 2);
ShowList(list);
Console.WriteLine("----------------------------------");
Console.WriteLine("按值查找c");
Console.WriteLine("找到值={0},{0}的索引是={1}", list[list.Locate("c")], list.Locate("c"));
Console.WriteLine("----------------------------------");
Console.WriteLine("获取第二个元素={0}", list.GetElem(2));
Console.WriteLine("----------------------------------");
Console.WriteLine("清空list");
list.Clear();//这里只是设置了顺序表的可访问的空间为0
ShowList(list);
Console.WriteLine("list长度={0} list最后一个元素索引是={1} list IsEmpty={2}", list.GetLength(), list.Last, list.IsEmpty());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.Read();
}
static void ShowList(SeqList<string> list)
{
for (Int32 i = 0; i < list.GetLength(); i++)
Console.WriteLine(list[i]);
}
}
public interface IListDS
{
Int32 GetLength();//求长度
void Clear();//清空操作
bool IsEmpty();//判断线性表是否为空
void Append(T item);//附加操作
void Insert(T item, Int32 i);//插入操作
T Delete(Int32 i);//删除操作
T GetElem(Int32 i);///获取表元
Int32 Locate(T value);//按值查找
}
public class SeqList
{
private Int32 maxsize;//顺序表的容量
private T[] data;//数组,用于存储顺序表中的数据元素
private Int32 last;//指示顺序表最后一个元素的位置
//索引器
public T this[Int32 index]
{
get
{
if (index < 0 || index > last)
throw new IndexOutOfRangeException("索引超出了数组界限");
return data[index];
}
set
{
if (index < 0 || index > maxsize - 1)
throw new IndexOutOfRangeException("索引超出了数组界限");
data[index] = value;
last++;
}
}
//最后一个数据元素的位置属性
public Int32 Last
{
get { return last; }
}
//容量属性
public Int32 Maxsize
{
get { return maxsize; }
set { maxsize = value; }
}
//构造器
public SeqList(Int32 size)
{
data = new T[size];
maxsize = size;
last = -1;
}
//求顺序表的长度
public Int32 GetLength()
{
return last + 1;
}
//清空顺序表
public void Clear()
{
last = -1;
}
//判断顺序表是否为空
public bool IsEmpty()
{
return last == -1 ? true : false;
}
//判断顺序表是否为满
public bool IsFull()
{
return last == maxsize - 1 ? true : false;
}
//在顺序表的末尾添加新元素
public void Append(T item)
{
if (IsFull())
{
Console.WriteLine("List is full");
return;
}
data[++last] = item;
}
//在顺序表的第i个数据元素的位置插入一个数据元素
public void Insert(T item, Int32 i)
{
if (IsFull())
{
Console.WriteLine("List is full");
return;
}
if (i < 1 || i > last + 2)
{
Console.WriteLine("Position is error");
return;
}
if (i == last + 2)
{
data[last + 1] = item;
}
else
{
for (Int32 j = last; j >= i - 1; --j)
{
data[j + 1] = data[j];
}
data[i - 1] = item;
}
++last;
}
//删除顺序表的第i个数据元素
public T Delete(Int32 i)
{
T tmp = default(T);
if (IsEmpty())
{
Console.WriteLine("List is empty");
return tmp;
}
if (i < 1 || i > last + 1)
{
Console.WriteLine("Position is error");
return tmp;
}
else
{
tmp = data[i - 1];
for (Int32 j = i - 1; j < last; ++j)
{
data[j] = data[j + 1];
}
}
--last;
return tmp;
}
//获取顺序表的第i个数据元素
public T GetElem(Int32 i)
{
if (IsEmpty() || (i < 1) || (i > last + 1))
{
Console.WriteLine("List is empty or Position is error");
returndefault(T);
}
return data[i - 1];
}
//在顺序表中查找值为value的数据元素
public Int32 Locate(T value)
{
if (IsEmpty())
{
Console.WriteLine("List is empty");
return -1;
}
Int32 i = 0;
for (i = 0; i <= last; ++i)
{
if (value.Equals(data[i]))
break;
}
if (i > last)
return -1;
return i;
}
}
-----------------------------------------------------
时间复杂度分析
Int32 GetLength();//求长度
时间复杂度为O(1),这里就是固定的执行last + 1。
void Clear();//清空操作
时间复杂度为O(1),这里就是固定的执行last = -1;
bool IsEmpty();//判断线性表是否为空
时间复杂度为O(1)
void Append(T item);//附加操作
时间复杂度为O(1)
void Insert(T item, Int32 i);//插入操作
当插入的节点在线性表的最后,那么就是添加一个元素,所以时间复杂度是O(1)。
当插入节点在线性表的开头,那么被插入节点的后续都要向后移动。
所以时间复杂度为O(n)
T Delete(Int32 i);//删除操作
当删除节点在线性表的最后,时间复杂度为O(1)
当删除节点在线性表的开头,那么被删除节点的后续都要向前移动。
所以时间复杂度为O(n)
T GetElem(Int32 i);//获取表元
这个快,直接索引数组的元素,时间复杂度为O(1)
Int32 Locate(T value);//按值查找
最坏的情况就是一个for循环,把线性表的元素都循环对比一次,时间复杂度为O(n)
--------------------------------------------------------------------------------
运行截图