寫在前面,本篇文章,你將瞭解到
1.線性表的定義
2.線性表的抽象數據類型及一些基本操作
3.線性表的兩大結構介紹:順序存儲結構和鏈式存儲結構
4.順序存儲結構的插入與刪除,及優缺點
1.線性表的定義
字面意思上看,是具有像線一樣的性質的表。
例如:
- ①在某中心廣場上,分散着很多人,有大人,也有小孩子,也許還有一些小寵物,這些在廣場的人和動物的數據,對於整個廣場來說,不能算是線性結構
- ②我們小時候,放學的時候,老師總是讓我們排好隊,手拉手走出學校,而且老師會讓我們記住自己的前面和後面,以及拉手的小夥伴的人,每次都在固定的位置和固定牽手的人,我們各自都知道自己的前面和後面是誰,如果一根線把放學的隊伍串起來,這就可以稱爲線性表
題外話:按照次序排隊做事,遵守秩序從娃娃抓起,每個小朋友都知道自己的前後是誰,當有人不見了,小朋友就是監督員,老師能及時知道誰不見了,出門春遊時,老師也能很快的統計人數,有人丟失也能最快時間知道
(思緒滿千,不得不回憶一波,那大概是寡人最巔峯的時候,隨便牽妹子的手,拉遠了拉遠了,哈哈)
官方定義:
線性表(List):零個或多個數據元素的有限序列
關鍵地方:
- ①一個序列,元素之間是有順序的,當存在多個元素時,第一個元素無前驅,最後一個元素無後繼,其他每個元素都有且只有一個前驅和後繼
- ②線性表強調是有限的,元素個數也是有限的
如圖所示,1 作爲第一個元素只有一個後繼,2有一個前驅 1和一個後繼 3 ,n沒有後繼
線性表元素個數n(n大於等於0)定義爲線性表的長度,當n = 0時,稱爲空表
另外,在較複雜的線性表中,一個數據元素可以由若干個數據項組成。
例如:
班級名字的信息記錄,如下圖,每個數據元素代表一條數據,每條數據裏面,有學號,姓名,性別,住址,郵箱等數據項
2.線性表的抽象數據類型
我們先來看一個例子:
還是拿我們之前小時候小朋友排隊的例子,
- ①老師讓散亂到處跑的小朋友排好隊,並且長期使用這個順序,這就是一個線性表的創建和初始化過程
- ②排好隊後發現,有的小朋友個子高在前面,有的個子矮在後面,參差不齊,老師就讓小朋友解散重新排,這就是一個將線性表置空的操作
- ③排好隊以後,有家長髮現有的孩子好可愛,衣服很時尚,可能會問老師,第十個小朋友穿那麼可愛,叫什麼名字啊,老師就可以告訴家長叫什麼名字,這種根據位序得到數據元素也是一種線性表的操作
- ④老師要知道班級有多少個小朋友,於是排隊一個個數,這種就是獲得線性表的長度
- ⑤有些糊塗的家長,可能第一次來接孩子,不知道自己孩子在哪個班,於是一個個班級去問老師,XXX小朋友是不是在這裏啊,這種查找某個元素是否在線性表中也是線性表的基本操作
- ⑥當然,小朋友肯定有時候會加入新的成員或者有的小朋友長大了,需要到高年級的班裏學習,就會有人加入有人退出,對於線性表來說就是,插入數據和刪除數據
等等操作。。。。。。
由此可見,假如我們把小朋友以及對小朋友的一些安排,信息獲取,等操作就是線性表的抽象數據類型
ADT 線性表(List)
Data
線性表的數據對象
Operation
InitList(*L) 初始化操作
ListEmpty(L)線性表爲空則返回true
ClearList(*L)線性表清空
GetElem(L,i,*e)將線性表中的第i個元素返回給e
LocateElem(L,e)在線性表L中查找與e相等的元素,如果查找成功,返回該元素在表中的序號,若不成功,返回0
ListInsert(*L,i,e)在線性表的第i個位置插入e
ListDelete(*L,i,e)刪除線性表中第i個位置的元素,並用e返回其值
ListLength(L)返回線性表L的元素個數
endADT
在應用時,應用這些基本的線性表操作,可以完成一些更復雜的操作
3.線性表的順序存儲結構
定義: 線性表的順序存儲結構,指的是一段地址連續的存儲單元依次存儲線性表的數據元素
例如:
跟我們網吧開黑5連坐一樣,佔了空的位置,五個人按順序坐,哈哈哈哈哈,我們可以用一維數組來實現順序存儲結構,當我們在網吧找位子的時候,肯定是找風水寶地,比如在哪可以看到漂亮的妹子,然後放下東西佔好地,所以我們的第一個位置就非常關鍵,在線性表中,第一個位置是存儲空間的起始位置。
然後,我們有5個人,需要佔5個位置,我們估算這個線性表的最大容量,建立一個數組,長度就是這個數組的最大容量
可往往總有人因爲戀愛,女朋友的呼喚(來自單身狗的鄙視,哼哼)有人缺席,我們在用來打遊戲的座位實際上被使用的只有4個,有1個位置是空的,我們就可以叫其他同學、朋友一起來,往線性表中增加數據,當然最多隻能容納5個人,總不能一個人坐另一個人身上(寫到這,臉上露出了邪惡的笑容)
接下來,我們來看線性表的順序存儲結構代碼:
#define MAXSIZE 20 //存儲空間初試分配量
typedef int ElemType //ElemType類型根據實際情況而定,我們在這假定是int
typedef struct
{
ElemType data[MAXSIZE]; //數組存儲數據元素,最大值爲MAXSIZE
int length; //線性表當前長度
}SqList;
順序存儲結構的三個屬性:
- ①存儲空間的其實位置:數組data
- ②線性表的最大存儲容量:數組長度MaxSize
- ③線性表的當前長度:length
敲黑板!!!!!!!!注意!!!!!!
注意區分數組的長度和線性表的長度
- 數組長度:是存放線性表的存儲空間的長度,存儲分配後這個量一般是不變的,當然動態分配數組除外
- 線性表的長度:是指線性表中有多少個元素,隨着線性表的插入和刪除,這個數量在不斷變化
線性表的長度應該小於等於數組的長度
4.地址計算方法
當我們在數數的時候,通常第一反應都是從1開始,所以我們的線性表也不能免俗,起始也是1,但是C語言中的數組卻是從0開始第一個下標,於是就有了數組元素的序號和存放它的數組下標之間存在的對應關係,第i個元素是要存儲在數組下標爲 i -1 的位置。
用數組存儲順序表,數組空間要大於當前線性表的長度,因爲線性表中可以進行插入刪除操作
內存的地址,都是有編號的,就跟電影院的座位一樣,存儲器中的每個存儲單元都有自己的編號,這個編號稱爲地址。
假設每個數據佔用的是c個存儲單元,那麼線性表中第 i + 1個元素和第 i 個元素的存儲位置滿足關係:
所以,對於第 i 個元素來說,可以由A1推算得出,
5.順序存儲結構的插入與刪除
-
①對於線性表的順序存儲結構來說,我們要返回線性表中的第 i 個位置元素值返回,只要 i 在數組下標範圍內,我們返回數組中 i - 1 位置上的值就行,我們來看一組返回值的定義
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int StatusStatus GetElem(SqList L,int i, ElemType *e)
{
if (L.length == 0 || i < 1 || i > L.length)
return ERROR;
*e = L.data[ i - 1];
return OK;
} -
②插入操作
當我們要在線性表L中的第 i 個位置插入新元素 e, ListInsert(*L , i , e),就像你在排隊進地鐵站,或者排隊買票的時候,還有2個人就要輪到自己了,有個小姐姐有緊急的事情想排在你前面,那你就必須後退一步,不然小姐姐就沒辦法進隊伍,此時當你後退了以後,後面的所有人都得往後退
思路:
- 如果插入位置不合理,拋出異常
- 如果線性表長度大於數組長度,拋出異常或者動態增加容量
- 從最後一個元素開始向前遍歷到第 i 個位置,分別將它們都向後移動一個位置
- 將要插入的元素填入位置 i 處
- 表長 + 1
Status ListInsert(SqList *L, int i, ElemType e)
{
int k;
if (L ->length == MAXSIZE)
return ERROR;
if (i < 1 || i > L->length)
return ERROR;
if (i <= L-> length)
{
for ( k = L->length - 1, k > =i - 1, k--)
{
L -> data[k+1] = L->data[k];
}
}
L->data[i - 1] = e;
L->length++;
return OK;
}
- ③刪除操作
接着上面的例子,剛剛排到了你前面的小姐姐,突然被一個人抓住,說她騙錢,這個小姐姐,靈活的閃過了衆人的追堵,跑出了隊伍,此時隊伍後面的人又慢慢悠悠的往前移動了一步。。
思路:
- 如果刪除位置不合理,拋出異常
- 取出刪除元素
- 從刪除元素位置開始遍歷到最後一個元素位置,分別將它們都向前移動一個位置
- 表長 減1
Status ListDelete(SqList *L,int i,ElemType *e)
{
int k;
if (L->length == 0)
return ERROE;
if (i < 1 || i>L->length)
return ERROR;
*e = L->data[i-1];
if (i < L->length)
{
for (k = i; k<L->length; k++)
{
L->data[k-1] = L->data[k];
}
}
L->length--;
return OK;
}
總結:
線性表順序存儲結構的優缺點:
優點:
- 1.不需要爲表示表中元素之間的邏輯關係增加額外空間
- 2.可以快速存取表中任一位置的元素
缺點:
- 1.插入和刪除操作需要移動大量元素
- 2.當線性表的長度變化時,不好確定存儲空間容量
- 3.容易造成存儲空間的碎片