C# 資料結構 線性表
阿新 • • 發佈:2019-01-14
何為線性表
線性表(List):零個或多個數據元素的有限序列。
線性表的實現方式有下面幾種
順序表
單鏈表 ( 雙向連結串列 迴圈連結串列)
操作:
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); //查詢 返回第index個位置元素 int Locate(T value); //查詢 查詢與給定值相等的元素 }
順序儲存
線性表的順序儲存結構,指的是用一段 地址連續的儲存單元 依次儲存線性表的資料元素。
儲存結構:一維陣列
三個屬性:
1.儲存空間的起始位置:陣列data 它的儲存位置就是儲存空間的儲存位置
2.線性表的最大儲存容量:陣列長度size
3.線性表的當前長度:count
/// 順序表實現方式 class SeqList<T>:IListDS<T> { private T[] data; //1.用來儲存資料 data private int count = 0; //3.線性表當前長度count public SeqList(int size) //2.最大容量size { data = new T[size]; count = 0; } //初始化操作 public SeqList():this(10)//預設建構函式 容量是10 { } //取得資料的個數 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; } }
分析:適合 元素個數變化不大、常存、取資料的應用
1.(查詢)存、讀 ,不管在那個位置,時間複雜度都為O(1);
2.插入、刪除,時間複雜度O(n);插入或刪除尾部資料元素時為O(1)。
優點:無須為表示表中元素之間的邏輯關係而增加額外的儲存空間;可以快速的存取表中任一位置的與元素。
缺點:插入和刪除操作需要移動大量元素;當線性表長度變化較大時,難以確定儲存空間的容量;造成儲存空間的碎片。
鏈式儲存
單鏈表 採用鏈式儲存結構,用一組任意的儲存單元存放線性表的元素
資料域:儲存資料元素資訊的域 指標域:儲存直接後繼位置的域
結點:資料域和指標域組成資料元素ai的儲存映像。
頭指標與頭結點:頭指標即為頭結點的指標域
儲存結構:結點
1.資料data
2.指標next
class Node<T>
{
private T data; //1.資料data
private Node<T> next; //2.指標next 用來指向下一個元素
public Node()
{
data = default(T);
next = null;
}
public Node(T value)
{
data = value;
next = null;
}
public Node(T value, Node<T> next)
{
this.data = value;
this.next = next;
}
public Node(Node<T> next)
{
this.next = next;
}
public T Data
{
get { return data; }
set { data = value; }
}
public Node<T> Next
{
get { return next; }
set { next = value; }
}
}
連結串列實現
class LinkList<T>:IListDS<T>
{
private Node<T> head;//儲存一個頭結點
public LinkList() //初始化
{
head = null;
}
//取得資料個數
public int GetLength()
{
if (head == null) return 0;
Node<T> temp = head;
int count = 1;
while (true)
{
if (temp.Next != null)
{
count++;
temp = temp.Next;
}
else
{
break;
}
}
return count;
}
//清空
public void Clear()
{
head = null;
}
//是否為空
public bool IsEmpty()
{
return head == null;
}
//新增
public void Add(T item)
{
Node<T> newNode = new Node<T>(item);//根據新的資料建立一個新的節點
//如果頭結點為空,那麼這個新的節點就是頭節點
if (head == null)
{
head = newNode;
}
else
{//把新來的結點放到 連結串列的尾部
//要訪問到連結串列的尾結點
Node<T> temp = head;
while (true)
{
if (temp.Next != null)
{
temp = temp.Next;
}
else
{
break;
}
}
temp.Next = newNode;//把新來的結點放到 連結串列的尾部
}
}
//插入
public void Insert(T item, int index)
{
Node<T> newNode = new Node<T>(item);
if (index == 0) //插入到頭節點
{
newNode.Next = head;
head = newNode;
}
else
{
Node<T> temp = head;
for (int i = 1; i <=index-1; i++)
{
//讓temp向後移動一個位置
temp = temp.Next;
}
Node<T> preNode = temp;
Node<T> currentNode = temp.Next;
preNode.Next = newNode;
newNode.Next = currentNode;
}
}
//刪除
public T Delete(int index)
{
T data = default(T);
if (index == 0) //刪除頭結點
{
data = head.Data;
head = head.Next;
}
else
{
Node<T> temp = head;
for (int i = 1; i <= index - 1; i++) {
//讓temp向後移動一個位置
temp = temp.Next;
}
Node<T> preNode = temp;
Node<T> currentNode = temp.Next;
data = currentNode.Data;
Node<T> nextNode = temp.Next.Next;
preNode.Next = nextNode;
}
return data;
}
//查詢(索引器)
public T this[int index]
{
get
{
Node<T> temp = head;
for (int i = 1; i <= index; i++) {
//讓temp向後移動一個位置
temp = temp.Next;
}
return temp.Data;
}
}
//查詢
public T GetEle(int index)
{
return this[index];
}
//查詢
public int Locate(T value)
{
Node<T> temp = head;
if (temp == null)
{
return -1;
}
else
{
int index = 0;
while (true)
{
if (temp.Data.Equals(value))
{
return index;
}
else
{
if (temp.Next != null)
{
temp = temp.Next;
}
else
{
break;
}
}
}
return -1;
}
}
}
分析:元素個數變化大、不知道有多大 頻繁插入、刪除資料
1.(查詢):O(n)
2.插入、刪除:從整個演算法O(n)。但是從第i位置插入多個結點,只需第一次找到第i位置的指標,此時O(n),接下來只是簡單的通過賦值移動指標,此時O(1)
與順序表比較
儲存分配方式 時間效能 空間效能