數據結構與算法之----線性表
01線性表
1.線性表的判斷方式就是元素有且只有一個直接前驅和直接後繼,元素可以為空,此時叫做空表
2.抽象數據類型標準格式
ADT 抽象數據類型名
DATA
數據元素之間邏輯關系的定義
Operation
操作
endADT
3.操作偽代碼
Operation
InitList(*L): 初始化操作,建立一個空的線性表L
ListEmpty(L): 判斷線性表是否為空表,如果為空返回true,否則返回false
ClearList(*L): 將線性表清空(實際情況不是刪除元素,而是將內存中的元素全部設置成0)
GetElem(L,i,*e): 將線性表L中的第i個位置元素值返回給e
LocateElem(L,e): 在線性表L中查找與給定值e相等的元素,如果查找成功,返回該元素在表中的序號表示成功,失敗返回0
ListInsert(*L,i,e): 在線性表L中第i個位置插入新元素e
ListDelete(*L,i,*e): 刪除線性表L中第i個位置元素,並用e返回其值
ListLength(L): 返回線性表L的元素個數
endADT
4.實際問題
提問:實現兩個線性表A,B的並集操作
思路:循環遍歷集合B中的每個元素,判斷當前元素是否存在於A中,如果不存在插入到A中即可
1.寫一個for循環,根據循環條件我需要知道循環的範圍,即就是B集合的長度
for (int i = 0; i <= ListLength(B); i++)
2.拿到的每一個B集合中的元素,判斷在A集合中是否存在(前提是A集合或者B集合不是空表)
int j = LocateElem(A,i);
if (j == 0) NSLog(@“A集合中並沒有該元素”);
else NSLog(@“A集合中存在該元素”);
3.將已經確定不存在的元素插入到A集合中
int La = ListLength(A);
ListInsert(*A,La-1,j);
for (int i = 0; i <= ListLength(B); i++) {
int j = LocateElem(A,i);
if (j == 0) {
NSLog(@“A集合中並沒有該元素”);
int La = ListLength(A);
ListInsert(*A,La-1,j);
}
else {
NSLog(@“A集合中存在該元素”);
}
官方答案:
La_len = ListLength(La);
Lb_len = ListLength(Lb);
for (int i = 0 ; i <= Lb_len ; i++)
{
GetElem(Lb,i,*e); //將線性表Lb中的第i個位置元素值返回給e
if ( !LocateElem (La,e) )
{
ListInsert (La,++La_len,e);
}
}
5.順序存儲結構
a1 a2 a3 a4 a5 …… aN:內存中提供一塊兒地方把相同數據類型的元素依次寫入
結構封裝需要三個屬性:存儲空間起始位置;線性表最大存儲容量;線性表當前長度
a1 a2 a3
我想在a1和a2之間插入b1
1.L最大存儲容量
2.a3開始依次往後移動一個單位
3.插入b1
6.實際問題
獲得元素
1 < i < ListLength(L);
e = L.data[i-1];
插入操作
思路:如果插入位置不合理,拋出異常;如果線性表長度大於等於數組長度,則拋出異常或動態增加數組容量;從最後一個元素開始向前遍歷到第i個位置,分別將它們都向後移動一個位置
7.線性表順序存儲結構優缺點
在存儲,讀取數據時,不管是哪個位置時間復雜度都是O(1).而在插入或者刪除時,時間復雜度都是O(n).
無需為表示表中元素之間的邏輯關系而增加額外的存儲空間
可以快速存取表中任意位置的元素
插入和刪除操作需要移動大量元素
當線性表長度變化較大時,難以確定存儲空間的容量
容易造成存儲空間的碎片(申請空間時是整塊兒的)
8.鏈式存儲結構
順序存儲結構中最大的缺點就是插入和刪除元素時需要移動大量元素,耗費時間.導致這個問題的原因就是相鄰兩個元素的存儲位置在內存中是緊挨著的,中間沒有任何空隙,當然就無法快速插入和刪除.所以引入鏈式存儲結構概念
特點:用一組任意的存儲單元存儲線性表的數據元素,這組存儲單元可以存在內存中未被占用的任意位置.相鄰兩個元素之間可以相差很多內存空間距離,彼此用指針聯系
在鏈式存儲結構中,除了要存儲數據元素信息之外,還需要存儲它的後繼元素的存儲地址(指針)
存儲數據元素信息的域稱為數據域
存儲直接後繼位置的域稱為指針域
指針域中存儲的信息稱為指針或鏈
兩部分信息組成數據元素稱為存儲映像,也稱結點(Node)
單鏈表:鏈表中的每個結點中只包含一個指針域;第一個結點的存儲位置叫做頭指針,最後一個結點的指針為NULL
9.頭結點和頭指針的異同 //頭結點和第一個元素的結點是完全不同的兩個概念. 頭指針存儲的是第一個結點的地址
頭指針:是指鏈表指向第一個結點的指針,若鏈表有頭結點,則是指向頭結點的指針;無論鏈表是否為空,頭指針均不為空;頭指針是鏈表的必要元素
頭結點:為了操作的統一和方便設立的,放在第一個元素的結點之前,其數據一般沒有意義(但是可以用來存放鏈表的長度);有了頭結點,對在第一個元素結點前插入結點和刪除第一結點起操作與其他結點的操作就統一了;頭結點不一定是鏈表的必須要素;頭結點中的數據域可以為空,但是指針域應該不會為空
理解:所謂頭結點就是放在鏈表第一個元素前的一個結點,沒有實際意義,可以存放鏈表的長度.如果鏈表中有頭結點的話那麽頭指針指向的就是頭結點,如果沒有的話指向的就是第一個結點(即第一個元素).頭結點可有可無,頭指針必須存在.
10實際問題
假設p是指向線性表第i個元素的指針,則該結點ai的數據域我們可以用p->data表示,它的值是一個數據元素,結點ai的指針域我們可以用p->next表示,它的值是一個指針.那麽p->next指向的是第i+1個元素,也就是說它是指向第ai+1的指針
提問:如果p->data = ai,那麽p->next->data = ?
思路:題中說p->data代表ai元素的數據域,那麽p->next代表的是ai元素的指針域,代表指向ai+1元素的指針,所以p->next->data代表的是ai+1元素的數據域,也就是數據元素,即ai+1.
數據結構與算法之----線性表