线性表的逻辑结构
线性结构的特点是数据元素之间存在一对一的线性关系。即:(1)除第一个元素之外所有元素位置前面都只有一个元素,称为直接前驱(2)出最后一个元素之外所有元素位置后面都只有一个元素称为直接后继。
根据线性表的基本操作作出相应的规约,即接口:
interface IListDS
{
int GetLength();//获取长度
void Clear();//清空表
bool IsEmpty();//判空
void Append(T item);//末尾添加元素
void Insert(T item,int index);//某一位置前插入元素
T Delete(int index);//某一位置删除元素
T GetElem(int index);//获取某一索引所对应的元素
int Locate(T val);//查找元素所在位置
T this[int index] { get; set; }//索引器
}
线性表的存储结构
线性表的存储结构包括顺序存储和链式存储。顺序存储的元素,逻辑上相邻的元素其物理位置上也相邻,链式存储的元素,逻辑上相邻的元素物理位置上不一定相邻。这里以单向链表为例。分别实现相应功能。
顺序存储:
class SeqList:IListDS
{
private int count;//数据的个数
private T[] data;//存数数据的容器
/// <summary>
/// 提供两个构造器,第二个容器初始大小默认为10
/// </summary>
/// <param name="size"></param>
public SeqList(int size)
{
data = new T[10];
}
public SeqList():this(10)
{
}
public int GetLength()
{
return count;
}
public void Clear()
{
count = 0;
}
public bool IsEmpty()
{
return count == 0;
}
public void Append(T item)
{
if (count == data.Length)
{
throw new Exception("表满了,无法继续存储!");
}
else//使用else逻辑更加清晰
{
data[count] = item;
count++;
}
}
public void Insert(T item, int index)
{
if (count == data.Length)
{
throw new Exception("表满了,无法继续存储!");
}
else
{
if (index < 0 || index >= count)
{
throw new Exception("索引超出范围!");
}
else
{
for (int i = count; i > index; i--)
{
data[i] = data[i - 1];
}
data[index] = item;
count++;
}
}
}
public T Delete(int index)
{
if (index < 0 || index >= count)
{
throw new Exception("索引超出范围!");
}
else
{
T temp = data[index];
for (int i = index; i < count-1; i++)
{
data[i] = data[i + 1];
}
count--;
return temp;
}
}
public T GetElem(int index)
{
if (index < 0 || index >= count)
{
throw new Exception("索引超出范围!");
}
else
{
return data[index];
}
}
public int Locate(T val)
{
for (int i = 0; i < count; i++)
{
if (data[i].Equals(val))
{
return i;
}
}
return -1;
}
public T this[int index]
{
get { return GetElem(index); }
set
{
if (index < 0 || index >= count)
{
throw new Exception("索引超出范围!");
}
else
{
data[index] = value;
}
}
}
}
链式存储:
class LinkList:IListDS
{
public Node head;//头结点,存储链表第一个元素
public LinkList()
{
head = null;
}
public int GetLength()
{
if (head == null)
{
return 0;
}
else
{
int count = 0;
Node<T> temp = head;
while (temp!=null)
{
count++;
temp = temp.Next;
}
return count;
}
}
public void Clear()
{
head = null;
}
public bool IsEmpty()
{
return head == null;
}
public void Append(T item)
{
if (head == null)
{
head = new Node<T>(item);
}
else
{
Node<T> temp = head;
while (temp.Next!=null)
{
temp = temp.Next;
}
temp.Next=new Node<T>(item);
}
}
public void Insert(T item, int index)
{
if (index < 0 || index >= this.GetLength())
{
throw new Exception("索引超出界限!");
}
else
{
if (index == 0)
{
Node<T> locate = head;
head=new Node<T>(item);
head.Next = locate;
}
else
{
Node<T> temp = head;
int i = 0;
while (i < index-1)//找到index前面一位的结点
{
temp = temp.Next;
i++;
}
Node<T> locate = temp.Next;
temp.Next = new Node<T>(item);
temp.Next.Next = locate;
}
}
}
public T Delete(int index)
{
if (index < 0 || index >= this.GetLength())
{
throw new Exception("索引超出界限!");
}
else
{
if (index == 0)
{
T data = head.Data;
head = head.Next;
return data;
}
else
{
Node<T> temp = head;
int i = 0;
while (i < index-1)//找到index前面一位的结点
{
temp = temp.Next;
i++;
}
T data = temp.Next.Data;
temp.Next = temp.Next.Next;
return data;
}
}
}
public T GetElem(int index)
{
if (index < 0 || index >= this.GetLength())
{
throw new Exception("索引超出界限!");
}
else
{
if (index == 0)
{
T data = head.Data;
return data;
}
else
{
Node<T> temp = head;
int i = 0;
while (i < index)//找到index位置的结点
{
temp = temp.Next;
i++;
}
T data = temp.Data;
return data;
}
}
}
public int Locate(T val)
{
int i = 0;
Node<T> temp = head;
while (temp!=null)
{
if (temp.Data.Equals(val))
{
break;
}
else
{
i++;
temp = temp.Next;
}
}
return temp == null ? -1 : i;
}
public T this[int index]
{
get { return GetElem(index); }
set
{
if (index < 0 || index >= this.GetLength())
{
throw new Exception("索引超出界限!");
}
else
{
if (index == 0)
{
head.Data = value;
}
else
{
Node<T> temp = head;
int i = 0;
while (i < index)//找到index位置的结点
{
temp = temp.Next;
i++;
}
temp.Data = value;
}
}
}
}
}
注意:链式存储需要定义一个节点类来存储他的每一个结点的信息(结点的数据信息,下一个节点)
class Node<T>
{
private T data;
private Node<T> next;//用来指向下一个元素
//多种构造方法
public Node(T data, Node<T> next)
{
this.data = data;
this.next = next;
}
public Node(T data)
{
this.data = data;
}
public Node(Node<T> next)
{
this.next = next;
}
public Node()
{
data = default(T);//获取该类型的默认值
next = null;
}
public T Data { get { return data; } set { data = value; } }
public Node<T> Next { get { return next; } set { next = value; } }
}
对两者进行检验:
static void Main(string[] args)
{
LinkList myInt = new LinkList();
// SeqList myInt = new SeqList();
myInt.Append(1);
myInt.Append(2);
myInt.Append(3);
myInt[2] = 5;
myInt.Insert(45, 0);
Console.WriteLine(myInt.Locate(2));
myInt.Delete(2);
Console.WriteLine(myInt.Locate(2));
Console.WriteLine(myInt.IsEmpty());
for (int i = 0; i < myInt.GetLength(); i++)
{
Console.Write(myInt[i]+”;”);
}
Console.ReadKey();
}
实验结构一致且符合预期: