欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C#數(shù)據(jù)結(jié)構(gòu)與算法揭秘二

 更新時(shí)間:2012年10月29日 23:00:26   作者:  
上文對數(shù)據(jù)結(jié)構(gòu)與算法,有了一個(gè)簡單的概述與介紹,這篇文章,我們介紹一中典型數(shù)據(jù)結(jié)構(gòu)——線性結(jié)構(gòu)

上文對數(shù)據(jù)結(jié)構(gòu)與算法,有了一個(gè)簡單的概述與介紹,這篇文章,我們介紹一中典型數(shù)據(jù)結(jié)構(gòu)——線性結(jié)構(gòu)。

什么是線性結(jié)構(gòu),線性結(jié)構(gòu)是最簡單、最基本、最常用的數(shù)據(jù)結(jié)構(gòu)。線性表是線性結(jié)構(gòu)的抽象(Abstract), 線性結(jié)構(gòu)的特點(diǎn)是結(jié)構(gòu)中的數(shù)據(jù)元素之間存在一對一的線性關(guān)系。 這

種一對一的關(guān)系指的是數(shù)據(jù)元素之間的位置關(guān)系,即: (1)除第一個(gè)位置的數(shù)據(jù)元素外,其它數(shù)據(jù)元素位置的前面都只有一個(gè)數(shù)據(jù)元素; (2)除最后一個(gè)位置的數(shù)據(jù)元素外,其它數(shù)據(jù)元素位置的后面都只有一個(gè)元素。也就是說,數(shù)據(jù)元素是一個(gè)接一個(gè)的排列。因此,可以把線性結(jié)構(gòu)想象為一種數(shù)據(jù)元素序列的數(shù)據(jù)結(jié)構(gòu)。

線性結(jié)構(gòu)(List)是由 n(n≥0)個(gè)相同類型的數(shù)據(jù)元素構(gòu)成的有限序列。對于這個(gè)定義應(yīng)該注意兩個(gè)概念:一是“有限” ,指的是線性表中的數(shù)據(jù)元素的個(gè)數(shù)是有限的,線性表中的每一個(gè)數(shù)據(jù)元素都有自己的位置(Position)。本書不討論數(shù)據(jù)元素個(gè)數(shù)無限的線性表。二是“相同類型” ,指的是線性表中的數(shù)據(jù)元素都屬于同一種類型。這體現(xiàn)在我們常用的數(shù)據(jù)結(jié)構(gòu)就是數(shù)組,泛型等等他們都是線性結(jié)構(gòu)的。

他們之間的關(guān)系 是:線性表的形式化定義為:線性表(List)簡記為 L,是一個(gè)二元組, L = (D, R) 其中:D 是數(shù)據(jù)元素的有限集合。 R 是數(shù)據(jù)元素之間關(guān)系的有限集合。

線性結(jié)構(gòu)的基本操作如下:

public interface IListDS<T> {
int GetLength(); //求長度
void Clear(); //清空操作
bool IsEmpty(); //判斷線性表是否為空
void Append(T item); //附加操作
void Insert(T item, int i); //插入操作
T Delete(int i); //刪除操作
T GetElem(int i); //取表元
int Locate(T value); //按值查找
}

這里為什么是IListDS是與。net自帶IList相區(qū)別。對每個(gè)方法解釋如下:

1、求長度:GetLength()
初始條件:線性表存在;
操作結(jié)果:返回線性表中所有數(shù)據(jù)元素的個(gè)數(shù)。
2、清空操作:Clear()
初始條件:線性表存在且有數(shù)據(jù)元素;
操作結(jié)果:從線性表中清除所有數(shù)據(jù)元素,線性表為空。
3、判斷線性表是否為空:IsEmpty()
初始條件:線性表存在;
操作結(jié)果:如果線性表為空返回 true,否則返回 false。
4、附加操作:Append(T item)
初始條件:線性表存在且未滿;
操作結(jié)果:將值為 item 的新元素添加到表的末尾。
5、插入操作:Insert(T item, int i)
初始條件:線性表存在,插入位置正確()(1≤i≤n+1,n 為插入前的表長)。
操作結(jié)果:在線性表的第 i 個(gè)位置上插入一個(gè)值為 item 的新元素,這樣使得原序號為 i,i+1,…,n 的數(shù)據(jù)元素的序號變?yōu)?i+1,i+2,…,n+1,插入后表長=原表長+1。 
6、刪除操作:Delete(int i)
初始條件:線性表存在且不為空,刪除位置正確(1≤i≤n,n 為刪除前的表長)。
操作結(jié)果:在線性表中刪除序號為 i 的數(shù)據(jù)元素,返回刪除后的數(shù)據(jù)元素。刪除后使原序號為 i+1,i+2,…,n 的數(shù)據(jù)元素的序號變?yōu)?i,i+1,…,n-1,刪除后表長=原表長-1。
7、取表元:GetElem(int i)
初始條件:線性表存在,所取數(shù)據(jù)元素位置正確(1≤i≤n,n 為線性表的表長) ; 操作結(jié)果:返回線性表中第 i 個(gè)數(shù)據(jù)元素。
8、按值查找:Locate(T value)
初始條件:線性表存在。
操作結(jié)果:在線性表中查找值為 value 的數(shù)據(jù)元素,其結(jié)果返回在線性表中首次出現(xiàn)的值為 value 的數(shù)據(jù)元素的序號,稱為查找成功;否則,在線性表中未找到值為 value 的數(shù)據(jù)元素,返回一個(gè)特殊值表示查找失敗。

先看最簡單的線性結(jié)構(gòu)——順序表

什么是順序表,線性結(jié)構(gòu)的順序存儲是指在內(nèi)存中用一塊地址連續(xù)的空間依次存放線性表的數(shù)據(jù)元素,用這種方式存儲的線性就叫順序表(Sequence List)。

順序表儲存結(jié)構(gòu)如圖所示

假設(shè)順序表中的每個(gè)數(shù)據(jù)元素占w個(gè)存儲單元, 設(shè)第i個(gè)數(shù)據(jù)元素的存儲地址為Loc(ai),則有: Loc(ai)= Loc(a1)+(i-1)*w 1≤i≤n 式中的Loc(a1)表示第一個(gè)數(shù)據(jù)元素a1的存儲地址,也是順序表的起始存儲地址,稱為順序表的基地址(Base Address). 這里我們舉個(gè)例子吧,比如你去酒店的時(shí)候,知道101號房間的基準(zhǔn)的位置,你要去111號房間,你知道每個(gè)房間之間的距離是5,那里只需要前進(jìn)50米。順序表的地址運(yùn)算就這么簡單。

而順序表是繼承與線性結(jié)構(gòu),他的源代碼又是這個(gè)樣子的。

public class SeqList<T> : IListDS<T> {
private int maxsize; //順序表的容量   順序表的最大容量
private T[] data; //數(shù)組,用于存儲順序表中的數(shù)據(jù)元素 用于存儲順序表的結(jié)構(gòu) 
private int last; //指示順序表最后一個(gè)元素的位置  

//索引器
public T this[int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}

//最后一個(gè)數(shù)據(jù)元素位置屬性
public int Last
{
get
{
return last;
}
}

//容量屬性
public int Maxsize
{
get
{
return maxsize;
}

set
{
maxsize = value;
}
}

//構(gòu)造器 進(jìn)行函數(shù)初始化工作

public SeqList(int size) 

{
data = new T[size];
maxsize = size;
last = -1;
}

//求順序表的長度
public int GetLength()
{
return last+1;
}

//清空順序表

//清除順序表中的數(shù)據(jù)元素是使順序表為空,此時(shí),last 等于-1。

public void Clear()
{
last = -1;
}

//判斷順序表是否為空

//如果順序表的 last 為-1,則順序表為空,返回 true,否則返回 false。
public bool IsEmpty()
{
if (last == -1)
{
return true;
}
else
{
return false;
}
}


//判斷順序表是否為滿

//如果順序表為滿,last 等于 maxsize-1,則返回 true,否則返回 false。
public bool IsFull()
{
if (last == maxsize-1)
{
return true;
}
else
{
return false;
}
}
//附加操作是在順序表未滿的情況下,在表的末端添加一個(gè)新元素,然后使順序表的last加1。

//在順序表的末尾添加新元素
public void Append(T item)
{
if(IsFull())
{
Console.WriteLine("List is full");
return;
}

data[++last] = item;
}
//順序表的插入是指在順序表的第i個(gè)位置插入一個(gè)值為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 時(shí),表示在順序表的末尾插入數(shù)據(jù)元素。 順序表上插入一個(gè)數(shù)據(jù)元素的步驟如下: 

//(1)判斷順序表是否已滿和插入的位置是否正確,表滿或插入的位置不正確不能插入;
//(2)如果表未滿和插入的位置正確,則將an~ai依次向后移動(dòng),為新的數(shù)據(jù)元素空出位置。在算法中用循環(huán)來實(shí)現(xiàn);
//(3)將新的數(shù)據(jù)元素插入到空出的第 i 個(gè)位置上;
//(4)修改 last(相當(dāng)于修改表長) ,使它仍指向順序表的最后一個(gè)數(shù)據(jù)元素。

//在順序表的第i個(gè)數(shù)據(jù)元素的位置插入一個(gè)數(shù)據(jù)元素
public void Insert(T item, int 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 (int j = last; j>= i-1; --j)
{
data[j + 1] = data[j];
}

data[i-1] = item;
}
++last;
}

算法的時(shí)間復(fù)雜度分析:順序表上的插入操作,時(shí)間主要消耗在數(shù)據(jù)的移動(dòng)上, 在第i個(gè)位置插入一個(gè)元素, 從ai到an都要向后移動(dòng)一個(gè)位置, 共需要移動(dòng)n-i+1
個(gè)元素,而i的取值范圍為 1≤i≤n+1,當(dāng)i等于 1 時(shí),需要移動(dòng)的元素個(gè)數(shù)最多,為n個(gè);當(dāng)i為n+1 時(shí),不需要移動(dòng)元素。設(shè)在第i個(gè)位置做插入的概率為pi,則平
均移動(dòng)數(shù)據(jù)元素的次數(shù)為n/2。這說明:在順序表上做插入操作平均需要移動(dòng)表中一半的數(shù)據(jù)元素,所以,插入操作的時(shí)間復(fù)雜度為O(n) 。

 

//順序表的刪除操作是指將表中第i個(gè)數(shù)據(jù)元素從順序表中刪除, 刪除后使原表長 為 n 的 表 (a1,a2, … ,ai-1,ai, ai+1, … ,an) 變 為 表 長 為 n-1的 表(a1,a2,…,ai-1,ai+1,…,an)。i的取值范圍為 1≤i≤n,i為n時(shí),表示刪除順序表末尾的數(shù)據(jù)元素。 

順序表上刪除一個(gè)數(shù)據(jù)元素的步驟如下:
(1)判斷順序表是否為空和刪除的位置是否正確,表空或刪除的位置不正
確不能刪除;
(2)如果表未空和刪除的位置正確,則將ai+1~an依次向前移動(dòng)。在算法中
用循環(huán)來實(shí)現(xiàn);
(3)修改 last(相當(dāng)于修改表長) ,使它仍指向順序表的最后一個(gè)元素。

//刪除順序表的第i個(gè)數(shù)據(jù)元素
public T Delete(int 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;
}

if (i == last+1)
{
tmp = data[last--];
}
else
{
tmp = data[i-1];
for (int j = i; j <= last; ++j)
{
data[j] = data[j + 1];
}
}

--last;
return tmp;
}

算法的時(shí)間復(fù)雜度分析:順序表上的刪除操作與插入操作一樣,時(shí)間主要消耗在數(shù)據(jù)的移動(dòng)上。在第i個(gè)位置刪除一個(gè)元素,從ai+1到an都要向前移動(dòng)一個(gè)位置,共需要移動(dòng)n-i個(gè)元素,而i的取值范圍為 1≤i≤n,當(dāng)i等于 1 時(shí),需要移動(dòng)的元素個(gè)數(shù)最多,為n-1 個(gè);當(dāng)i為n時(shí),不需要移動(dòng)元素。設(shè)在第i個(gè)位置做刪除的概率為pi,則平均移動(dòng)數(shù)據(jù)元素的次數(shù)為(n-1)/2。這說明在順序表上做刪除操作平均需要移動(dòng)表中一半的數(shù)據(jù)元素,所以,刪除操作的時(shí)間復(fù)雜度為O(n) 。

//取表元運(yùn)算是返回順序表中第 i 個(gè)數(shù)據(jù)元素,i 的取值范圍是 1≤i≤last+1。由于表是隨機(jī)存取的,所以,如果 i 的取值正確,則取表元運(yùn)算的時(shí)間復(fù)雜度為O(1) 。

//獲得順序表的第i個(gè)數(shù)據(jù)元素 
public T GetElem(int i)
{
if (IsEmpty() | | (i<1) | | (i>last+1))
{
Console.WriteLine("List is empty or Position is error!");
return default(T);
}

return data[i-1];
}
//順序表中的按值查找是指在表中查找滿足給定值的數(shù)據(jù)元素。 在順序表中完成該運(yùn)算最簡單的方法是:從第一個(gè)元素起依次與給定值比較,如果找到,則返回在順序表中首次出現(xiàn)與給定值相等的數(shù)據(jù)元素的序號,稱為查找成功;否則,在順序表中沒有與給定值匹配的數(shù)據(jù)元素,返回一個(gè)特殊值表示查找失敗。

//在順序表中查找值為value的數(shù)據(jù)元素
public int Locate(T value)
{
if(IsEmpty())
{
Console.WriteLine("List is Empty!");
return -1;
}

int i = 0;
for (i = 0; i <= last; ++i)
{
if (value.Equals(data[i]))
{
break;
}
}

if (i > last)
{
return -1;
}
return i;
}
}

算法的時(shí)間復(fù)雜度分析:順序表中的按值查找的主要運(yùn)算是比較,比較的次數(shù)與給定值在表中的位置和表長有關(guān)。當(dāng)給定值與第一個(gè)數(shù)據(jù)元素相等時(shí),比較次數(shù)為 1;而當(dāng)給定值與最后一個(gè)元素相等時(shí),比較次數(shù)為 n。所以,平均比較次數(shù)為(n+1)/2,時(shí)間復(fù)雜度為 O(n) 。

如:已知順序表 L,寫一算法將其倒置,即實(shí)現(xiàn)如圖 2.4 所示的操作,其中(a)為倒置前,(b)為倒置后。

我思考的思路就是以所在的中間數(shù)進(jìn)行前后調(diào)換。相應(yīng)的源代碼如下:

public void ReversSeqList(SeqList<int> L)
{
int tmp = 0;
int len = L.GetLength();
for (int i = 0; i<= len/2; ++i)
{
tmp = L[i];
L[i] = L[len - i];
L[len - i] = tmp;
}
}

該算法只是對順序表中的數(shù)據(jù)元素順序掃描一遍即完成了倒置, 所以時(shí)間復(fù)雜度為 O(n)。其中運(yùn)行效果如圖所示:

還譬如,我就我開發(fā)親身經(jīng)歷而言  在俄羅斯方塊這個(gè)項(xiàng)目中,我的順序結(jié)構(gòu)用的確實(shí)很多譬如初始化過程中。

// 初始化形狀集合,共七種形狀
_pieces = new List<PieceBase> { new I(), new L(), new I2(), new L2(), new N(), new N2(), new O(), new T() };
// 初始化方塊容器(用 Block 對象填滿整個(gè)容器)
Container = new Block[_rows, _columns];
for (int i = 0; i < _rows; i++)
{
for (int j = 0; j < _columns; j++)
{
var block = new Block();
block.Top = i * block.rectangle.ActualHeight;
block.Left = j * block.rectangle.ActualWidth;
block.Color = null;
Container[i, j] = block;
}
}

// 初始化下一個(gè)形狀的容器(用 Block 對象將其填滿)
NextContainer = new Block[4, 4];
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
var block = new Block();
block.Top = i * block.rectangle.ActualHeight;
block.Left = j * block.rectangle.ActualWidth;
block.Color = null;
NextContainer[i, j] = block;
}
}

// 創(chuàng)建一個(gè)新的形狀
CreatePiece();
// 呈現(xiàn)當(dāng)前創(chuàng)建出的形狀
AddPiece(0, 0);

// Timer 用于定時(shí)向下移動(dòng)形狀
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(_initSpeed);
_timer.Tick += _timer_Tick;
GameStatus = GameStatus.Ready;

你看看我用的初始化方塊容器,這個(gè)容器是二維數(shù)組,這就是一種明顯的順序表。將他top位置,left位置賦值,進(jìn)行一系列初始化工作。這就等同于順序表初始化操作。這個(gè)算法的復(fù)雜度為O(n²)。

本文中,我們討論了什么是線性結(jié)構(gòu),線性結(jié)構(gòu)有哪些特點(diǎn),并且詳細(xì)介紹了一個(gè)最簡單線性結(jié)構(gòu)順序表,并且通過源代碼對她進(jìn)行一些列的分析,最后還舉了兩個(gè)例子,讓我們更好的理解順序表。

相關(guān)文章

  • 用C#繪制九宮格形式的圖片

    用C#繪制九宮格形式的圖片

    大家好,本篇文章主要講的是用C#繪制九宮格形式的圖片,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • 關(guān)于ASP網(wǎng)頁無法打開的解決方案

    關(guān)于ASP網(wǎng)頁無法打開的解決方案

    asp網(wǎng)頁實(shí)際上就是動(dòng)態(tài)網(wǎng)頁,是在服務(wù)端執(zhí)行和解析的。有時(shí)也很奇怪,經(jīng)常遇到asp網(wǎng)頁無法打開的情況,下面小編給大家整理些關(guān)于asp網(wǎng)頁無法打開的解決方案,需要的朋友可以參考下
    2015-08-08
  • c# 模擬串口通信 SerialPort的實(shí)現(xiàn)示例

    c# 模擬串口通信 SerialPort的實(shí)現(xiàn)示例

    本文主要介紹了c# 模擬串口通信 SerialPort的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • C#實(shí)現(xiàn)ProperTyGrid自定義屬性的方法

    C#實(shí)現(xiàn)ProperTyGrid自定義屬性的方法

    這篇文章主要介紹了C#實(shí)現(xiàn)ProperTyGrid自定義屬性的方法,主要通過接口ICustomTypeDescriptor實(shí)現(xiàn),需要的朋友可以參考下
    2014-09-09
  • C#字體池技術(shù)實(shí)現(xiàn)代碼詳解

    C#字體池技術(shù)實(shí)現(xiàn)代碼詳解

    在本篇文章里小編給大家整理的是關(guān)于C#字體池技術(shù)實(shí)現(xiàn)代碼詳解內(nèi)容,有需要的朋友們可以學(xué)習(xí)下。
    2019-11-11
  • C#圖像透明度調(diào)整的方法

    C#圖像透明度調(diào)整的方法

    這篇文章主要介紹了C#圖像透明度調(diào)整的方法,涉及C#操作圖像透明度的相關(guān)技巧,需要的朋友可以參考下
    2015-04-04
  • 使用C#來編寫一個(gè)異步的Socket服務(wù)器

    使用C#來編寫一個(gè)異步的Socket服務(wù)器

    這篇文章主要介紹了使用C#來編寫一個(gè)異步的Socket服務(wù)器,通過無阻塞機(jī)制來獲取更高的處理效率,需要的朋友可以參考下
    2015-07-07
  • C#中按字符串截取長字符串實(shí)例

    C#中按字符串截取長字符串實(shí)例

    這篇文章主要介紹了C#中按字符串截取長字符串的實(shí)現(xiàn)方法,以實(shí)例形式展示了C#中正則匹配截取字符串的技巧,需要的朋友可以參考下
    2014-11-11
  • jQuery結(jié)合C#實(shí)現(xiàn)上傳文件的方法

    jQuery結(jié)合C#實(shí)現(xiàn)上傳文件的方法

    這篇文章主要介紹了jQuery結(jié)合C#實(shí)現(xiàn)上傳文件的方法,涉及C#文件上傳的相關(guān)技巧,需要的朋友可以參考下
    2015-04-04
  • c#程序刪除自身代碼示例分享

    c#程序刪除自身代碼示例分享

    偶然看到一個(gè)可以自刪除的程序,于是了解下如何實(shí)現(xiàn)。然后整理如下,需要的朋友可以參考下
    2014-03-03

最新評論