陣列與鏈結串列 Array and Linked List -...

31
講師:洪安 陣列與鏈結串列 Array and Linked List 1

Transcript of 陣列與鏈結串列 Array and Linked List -...

Page 1: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

講師:洪安

陣列與鏈結串列Array and Linked List

1

Page 2: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

大綱

2

結構陣列

鏈結串列

單向鏈結串列之資料型態

單向鏈結串列之基本運算

課堂練習

Page 3: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

優點 使用容易

缺點 刪除與插入造成資料移動頻繁

浪費不必要之記憶體

class student{

int math;int english;int computer;

};

int main(){

student s[5];return 0;

}

結構陣列

3

math

english

computer

s

student student student student student

[0] [1] [2] [3] [4]

Page 4: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

動態記憶體配置 (1/2) new運算子會配置一個int所需要的空間,並傳回該空

間的位址,所以您使用指標ptr來儲存這個位址 int *ptr = new int;

如果要在配置完成後指定儲存值,則可以如此宣告 int *ptr = new int(100);

4

#include <iostream> using namespace std;int main() {

int *ptr = new int(100); cout << "空間位置:" << ptr << endl;cout << "空間儲存值:" << *ptr << endl;

*ptr = 200; cout << "空間位置:" << ptr << endl;cout << "空間儲存值:" << *ptr << endl;delete ptr;

return 0; }

4

Page 5: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

動態記憶體配置 (2/2) 動態配置陣列空間 int *arr = new int[1000];

歸還配置陣列空間給記憶體 delete [] arr;

5

#include <iostream>using namespace std; int main() {

int size = 0; cout << "請輸入陣列長度:"; cin >> size;

int *arr = new int[size]; cout << "指定元素值:" << endl; for(int i = 0; i < size; i++) {

cout << "arr[" << i << "] = "; cin >> *(arr+i);

}

cout << "顯示元素值:" << endl; for(i = 0; i < size; i++) {

cout << "arr[" << i << "] = " << *(arr+i) << endl; } delete [] arr; return 0;

}

5

Page 6: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

複習:動態記憶體配置

動態記憶體配置則是:

當程式執行到一半, 發現它需要一塊記憶體空間來存放資料, 才向系統索取一塊記憶體空間

當此記憶體空間用不到時, 也可隨時將之釋放供其它程式使用

動態記憶體配置的特色:有需要, 才配置!

6

Page 7: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

大綱

結構陣列

鏈結串列

單向鏈結串列之資料型態

單向鏈結串列之基本運算

課堂練習

7

Page 8: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

鏈結串列 Linked List

定義

由一組節點(node)所構成

各節點之間並不一定占用連續的Memory空間

各節點的型態不一定相同

插入節點、刪除節點方便 因為只改變指標

僅支援循序存取,不支援隨機存取

可任意(動態)增加、刪除空間

8

Page 9: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

陣列與鏈結串列比較陣列 鏈結串列

占用連續的記憶體空間 可以非連續

各元素型態皆相同 各節點型態不必一定相同

不支援串列之共享 支援

插入、刪除元素麻煩(因為需挪移元素)

方便

無法動態增加、刪除空間 可以

可支援循序及隨機存取 僅支援循序存取

可靠度高 低,因為指標斷裂,資料就遺失

循序存取速度快 慢,因為必須先讀取指標9

Page 10: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

靜態與動態結構

class node{

資料型態變數名稱; //如 : int data;

node *next;};node c;node *head;c.next = NULL;head = NULL;

head = new node;head->next = NULL;

(new)

node

資料

NULLnode *

資料型態 變數名稱

next

c

node

資料

NULL

資料型態 變數名稱

next

node *

head

node *

10

Page 11: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

鏈結串列節點

節點:鏈結串列中最基本的單位

節點

下一個節點

資料

物件指標

節點 = 資料+ 物件指標

11

Page 12: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

定義鏈結串列節點結構

鏈結串列透過儲存元素在記憶體之位址為指標(Pointer)或鏈結(Link)取得下一個節點

定義節點結構

node

class node{

資料型態變數名稱; //如 : int data;

node *next;};

資料

下一個節點node *

資料型態 變數名稱

next

12

Page 13: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

單向鏈結串列

單向鏈結串列之類別如下圖所示

head:指向串列前端之指標

tail:指向串列尾端之指標

…鏈結起點 鏈結終點

head tail

NULL

13

Page 14: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

走訪鏈結串列 從head開始

依序存取節點中的next指標

直到存取到NULL為止

範例:print()

走訪鏈結串列並輸出每個節點之data值

14

Page 15: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

小練習 (建立鏈結串列節點)

定義一個鏈結串列節點類別如下圖所示,並使用head與tail指標指向動態配置之節點

data

next

(new)

node

10

NULLnode *

int

node *

head

node *

tail

15

1. 請定義Node類別,並設定LinkedList類別為其夥伴(friend class LinkedList;)

2. 請定義LinkedList類別,類別資料成員包含 head 與 tail

3. 請實作建構函數,內容包含新增一個節點,設定data為10 ,設定next為NULL,並讓head和tail指到此新增節點

4. 請實作print()函數

答案在7-15.cpp,請先自己試試看唷

Page 16: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

大綱

結構陣列

鏈結串列

單向鏈結串列之資料型態

單向鏈結串列之基本運算

課堂練習

16

Page 17: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

新增節點

動態配置一節點之記憶體

node *LinkedList::getnode () /* 此函數產生一個新節點 */

{

node *p;

p = new node;

if ( p == NULL)

{

cout << "記憶體不足" << endl;

exit(1);

}

return(p);

}

17

Page 18: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

釋放節點

歸還一個節點之記憶體

void LinkedList::freenode (node *p)

/* 此函數將節點還給記憶體 */

{

delete p;

}

18

Page 19: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

由鏈結串列加入一個節點

一個節點之插入有三種情況:

節點加於第一個節點之前

節點加於最後一個節點之後

加於節點中間任何一個位置

插入節點

head

… NULL

ptr

new tail

head

… NULL

ptr

tail new

new

… NULL

ptr

head tail

19

Page 20: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

插入節點

加於節點中間任何一個位置new

… NULL

ptr

head tail

×

new

… NULL

ptr

head tail

(1)

(2)

(3)

(4)

20

Page 21: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

插入節點void LinkedList::insert_node(Node *ptr, int value) {

Node *new_node = getnode();new_node -> data = value;new_node -> next = NULL;

if (ptr == NULL) { //加在串列首new_node -> next = head;head = new_node;

}else if (ptr == tail){ //加在串列尾 等同於 ptr->next == NULL;

ptr -> next = new_node;tail = tail -> next; //等同於 tail = new_node;

}else { //加在串列中間

new_node -> next = ptr -> next;ptr -> next = new_node;

}}

21

Page 22: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

插入節點前的動作 找到插入的位置指標,傳給 insert_node(node

*ptr, int value)

22

void LinkedList::insert(int value)

{

if(head==NULL) //串列為空{

head = getnode();

head->data=value;

head->next=NULL;

tail = head;

}

else //串列不為空{

insert_node(tail, value);

}

cout << "Insert Successful!" << endl;

}

Page 23: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

小練習 (插入鏈結串列節點)

延續上一個練習

修改建構函數為設定head, tail為NULL

寫一個使用者介面,輸入i,接著輸入一個數字value,可插入一筆資料節點中之data為value於串列最後 (insert, insert_node functions)

輸入其他則印出串列內容並結束

建立一個鏈結串列如下圖所示:

data

next

(new)

node

10

node *

int

node *

head

node *

tail

(new)

node

20

(new)

node

30

NULL23

答案在7-23.cpp,請先自己試試看唷

Page 24: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

刪除節點

由鏈結串列中刪除一個節點

一個節點之刪除有三種情況:

刪除第一個節點

刪除最後一個節點

刪除中間任何一個節點

head

… NULL

ptr

tail

head

… NULL

tail

previous

… NULL

ptr

head tail

NULL

24

Page 25: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

刪除節點

刪除中間任何一個節點

… NULL

ptr

head tail(1)

previous

… NULL

ptr

head tail

previous

×

(2)25

Page 26: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

刪除節點

26

void LinkedList::remove_node(Node *ptr) {if (ptr == head) { /* 第一種情況: 刪除第一個節點 */

head = head -> next;}else {

//尋找ptr的前一個節點Node *prev = head; /* 指向前一節點 */while (prev -> next != ptr) {

prev = prev -> next; }/* 第二種情況: 刪除最後一個節點 */if (ptr == tail) { /* 最後一個節點 */

prev -> next = NULL;tail = prev;

}/* 第三種情況: 刪除中間節點 */else {

prev -> next = ptr ->next; /* 圖(3)之步驟(1) */}

}freenode(ptr); /* 此函數將節點歸還給記憶體 */

}

Page 27: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

找到刪除節點的位置

27

Page 28: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

小練習 (刪除鏈結串列節點)

延續上一個練習

寫一個使用者介面,輸入d,接著輸入一個數字value,可將一筆資料節點中之data與value相同者刪除(假設輸入之value不會重覆)

28 答案在7-28.cpp,請先自己試試看唷

Page 29: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

尋找節點

走訪串列,尋找輸入和資料相同的節點

29

Page 30: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

小練習 (尋找鏈結串列節點)

延續上一個練習

寫一個使用者介面,輸入f,接著輸入一個數字value,可將一筆資料節點中之data與value相同者印出資料

30答案在7_LinkedList.cpp,請先自己試試看唷

Page 31: 陣列與鏈結串列 Array and Linked List - csie.ntu.edu.twr95116/CA200/slide/C7_ArrayLinkedList.pdf · 一個數字value,可將一筆資料節點中 之data與value相同者刪除(假設輸入

鏈結串列長度

計算鏈結串列之長度

int LinkedList::length () /* 此函數計算節點之鏈結長度*/{

int num=0;node *q = head;while (q != NULL) {

num ++;q = q->next;

}return(num);

}31