線性表
線性表是最簡單、最基本、最常用的數據結構。線性表是線性結構的抽象(Abstract),線性結構的特點是結構中的數據元素之間存在一對一的線性關係。這種一對一的關係指的是數據元素之間的位置關係,即:(1)除第一個位置的數據元素外,其它數據元素位置的前面都只有一個數據元素;(2)除最後一個位置的數據元素外,其它數據元素位置的後面都只有一個元素。也就是說,數據元素是一個接一個的排列。因此,可以把線性表想象爲一種數據元素序列的數據結構。
線性表就是位置有先後關係,一個接着一個排列的數據結構。
CLR中線性表
- c#1.1提供了一個非泛型接口IList接口,接口中的項是Object,實現IList接口的類有 :ArrayList,ListDictionary,StringCollection,stringDictionary。
- c# 2.0 提供了泛型的IList接口,實現了List接口的類有List。
C# List的基礎常用方法:
一、聲明:
1、List<T> mList = new List<T>();
//T爲列表中元素類型,現在以string類型作爲例子:
List<string> mList = new List<string>();
//以一個集合作爲參數創建List:
2、List<T> testList =new List<T>(IEnumerable<T> collection);
string[] temArr = { "Ha", "Hunter", "Tom", "Lily", "Jay", "Jim", "Kuku", "Locu"};
List<string> testList = new List<string>(temArr);
二、添加元素:
1、List.Add(T item)//添加一個元素
例:mList.Add("John");
2、List.AddRange(IEnumerable<T> collection)//添加一組元素
例:string[] temArr = {"Ha","Hunter","Tom","Lily","Jay","Jim","Kuku","Locu"};
mList.AddRange(temArr);
3、Insert(index, T item);//在index位置添加一個元素
例:mList.Insert(1,"Hei");
三、遍歷List中元素:
foreach(T element in mList)//T的類型與mList聲明時一樣
{
Console.WriteLine(element);
}
例:
foreach(s trings in mList)
{
Console.WriteLine(s);
}
四、刪除元素:
1、List. Remove(T item)刪除一個值
例:mList.Remove("Hunter");
2、List. RemoveAt(int index);刪除下標爲index的元素
例:mList.RemoveAt(0);
3、List. RemoveRange(int index,int count);
從下標index開始,刪除count個元素
例:mList.RemoveRange(3, 2);
五、判斷某個元素是否在該List中:
List. Contains(T item)返回true或false,很實用
例:if(mList.Contains("Hunter"))
{
Console.WriteLine("There is Hunter in the list");
}
else
{
mList.Add("Hunter");
Console.WriteLine("Add Hunter successfully.");
}
六、給List裏面元素排序:
List.Sort ()//默認是元素第一個字母按升序
例:mList.Sort();
七、給List裏面元素順序反轉:
List. Reverse ()//可以不List.Sort ()配合使用,達到想要的效果
例:mList.Sort();
八、List清空:
List. Clear ()
例:mList.Clear();
九、獲得List中元素數目:
List.Count ()//返回int值
例:in tcount = mList.Count();
Console.WriteLine("The num of elements in the list: "+count);
線性表接口的定義
public Program
{
static void Main(string[] args)
{
//使用我們自己的順序表
SeqList<string> seqList = new SeqList<string> ();
seqList.Add("123");
seqList.Add("456");
seqList.Add("789");
Console.WirteLine(seqList.GetEle(0));
Console.WirteLine(seqList[0]);
seqList.Insert("777");
for(int i = 0 ; i<seqList.GetLength();i++)
{
Console.WirteLine(seqList[i]+ " ");
}
}
}
//線性表的定義
public interface IListDS<T>
{
int GetLength();//求長度
void Clear();//清空操作
bool IsEmpty();//判斷線性表是否爲空
void Append(T item);//附加操作、添加元素 相當於Add
void Insert(T item , int i );//插入操作
T Delete(int i);//刪除操作
T GetElem(int i);//取表元
T this[int index]{get;};//定義一個索引器獲取元素
int Locate(T value);//按值查找
}
//線性表的實現
//順序表實現方式
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
{
}
//取得數據的個數
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.WirteLine("當前順序表已存滿,不允許在存入")
}
else
{
data[count] = item;
count++;
}
}
//插入
//順序表的插入是指在順序表的第i個位置插入一個值爲item的新元素,
//插入後使 原 表 長 爲 n 的 表 (a1,a2, … ,ai-1,ai,ai+1, … ,an) 成 爲 表
//長 爲 n+1 的 表(a1,a2,…,ai-1,item,ai,ai+1,…,an)。
//i的取值範圍爲 1≤i≤n+1,i爲n+1 時,表示在順序表的末尾插入數據元素。
//順序表上插入一個數據元素的步驟如下:
//(1)判斷順序表是否已滿和插入的位置是否正確,表滿或插入的位置不正確不能插入;
//(2)如果表未滿和插入的位置正確,則將an~ai依次向後移動,爲新的數據元素空出位置。在算法中用循環來實現;
//(3)將新的數據元素插入到空出的第 i 個位置上;
//(4)修改 last(相當於修改表長) ,使它仍指向順序表的最後一個數據元素。
public void Insert(T item , int i )
{
for(int j == count-1;j >= i ; j--)
{
data[i+1] = data[i];
}
data[i] = item ;
count ++ ;
}
//算法的時間複雜度分析:順序表上的插入操作,時間主要消耗在數據的移動上,
//在第i個位置插入一個元素, 從ai到an都要向後移動一個位置, 共需要移動n-i+1
//個元素,而i的取值範圍爲 1≤i≤n+1,當i等於 1 時,需要移動的元素個數最多,爲n個;
//當i爲n+1 時,不需要移動元素。設在第i個位置做插入的概率爲pi,則平均移動數據
//元素的次數爲n/2。這說明:在順序表上做插入操作平均需要移動表中一半的數據元素,
//所以,插入操作的時間複雜度爲O(n) 。
//元素的刪除
public T Delete(int i)
{
T temp = data[index];
for(int i = index+1 ; i < count ; i ++)
{
data[i-1] = data[i];//把數據向前移動
}
count -- ;
return temp;
}
//根據索引取元素
public T GetElem(int i)
{
if(index > = 0 && index < = count - 1)
{
return data[index];
}
else
{
Console.WirteLine("索引不存在");
return default(T);//取得一個類型的默認值
}
}
//根據索引器取元素
public T this[int index]
{
get
{
return GetEle(index);
}
}
//根據值判斷所在位置
public int Locate(T value)
{
for(int i = 0 ; i < count ; i ++)
{
if(data[i].Equal(value))
{
return i;
}
}
return -1;
}
}
這裏爲什麼是IListDS是與.net自帶IList相區別。對每個方法解釋如下:
1、求長度:GetLength()
初始條件:線性表存在;
操作結果:返回線性表中所有數據元素的個數。
2、清空操作:Clear()
初始條件:線性表存在且有數據元素;
操作結果:從線性表中清除所有數據元素,線性表爲空。
3、判斷線性表是否爲空:IsEmpty()
初始條件:線性表存在;
操作結果:如果線性表爲空返回 true,否則返回 false。
4、附加操作:Append(T item)
初始條件:線性表存在且未滿;
操作結果:將值爲 item 的新元素添加到表的末尾。
5、插入操作:Insert(T item, int i)
初始條件:線性表存在,插入位置正確()(1≤i≤n+1,n 爲插入前的表長)。
操作結果:在線性表的第 i 個位置上插入一個值爲 item 的新元素,這樣使得原序號爲 i,i+1,…,n 的數據元素的序號變爲 i+1,i+2,…,n+1,插入後表長=原表長+1。
6、刪除操作:Delete(int i)
初始條件:線性表存在且不爲空,刪除位置正確(1≤i≤n,n 爲刪除前的表長)。
操作結果:在線性表中刪除序號爲 i 的數據元素,返回刪除後的數據元素。刪除後使原序號爲 i+1,i+2,…,n 的數據元素的序號變爲 i,i+1,…,n-1,刪除後表長=原表長-1。
7、取表元:GetElem(int i)
初始條件:線性表存在,所取數據元素位置正確(1≤i≤n,n 爲線性表的表長) ; 操作結果:返回線性表中第 i 個數據元素。
8、按值查找:Locate(T value)
初始條件:線性表存在。
操作結果:在線性表中查找值爲 value 的數據元素,其結果返回在線性表中首次出現的值爲 value 的數據元素的序號,稱爲查找成功;否則,在線性表中未找到值爲 value 的數據元素,返回一個特殊值表示查找失敗。
線性表的實現方式
線性表的實現方式有下面幾種
1、順序表
2、單鏈表
3、雙向鏈表
4、循環鏈表
線性結構–順序表
在計算機內,保存線性表最簡單、最自然的方式,就是把表中的元素一個接一個的放進順序的存儲單元,這就是順序表的順序存儲(Sequence Storage)。線性表的順序存儲是指在內存中用一塊地址連續的空間依次存放線性表的數據元素,用這種方式存儲的線性表叫順序表(Sequence List)。順序表的特點是表中相鄰的數據元素在內存中存儲位置也相鄰。如圖所示:
順序表的存儲
假設順序表中每個數據元素佔w個存儲單元,設第i個數據元素的存儲地址爲Loc(ai),則有:Loc(ai) = Loc(a1) + (i-1)*w (1<=i <= n)式中Loc(a1)表示第一個數據元素a1的存儲地址,也是順序表的起始存儲地址,成爲順序表的基地址(Base Address)。也就是說只要知道數據元素的基地址和每個數據元素的存儲單元的個數就可以求出順序表中任何一個數據元素的存儲地址。並且,由於計算順序表中的每個數據元素存儲地址的時間相同,所以順序表具有任意存取的特點,(可以再任意位置存取東西)
c#語言中的數組在內存中佔用的存儲空間就是一組連續的存儲空間,因此,數組具有任意存取的特點。所以,數組天生具有表示順序表的數據存儲區域的特性。