指標、串列 (Linked List).

Slides:



Advertisements
Similar presentations
第一單元 建立java 程式.
Advertisements

基本概論 Basic concepts.
第九章 系 统 安 全 性 9.1 结构体 9.2 结构体型数组  9.3 结构体型指针 9.4 内存的动态分配 9.5 共用体
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
Linked List Operations
單向鏈結串列 Singly Linked Lists.
第6章 佇列(Queues) 6-1 佇列的基礎 6-2 佇列的表示法 6-3 環狀佇列 6-4 雙佇列.
第7章 结构体、联合体和枚举类型 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
資料結構 第3章 鏈結串列.
結構(struct).
第十一章 結構.
Visual C++ introduction
資料大樓 --談指標與陣列 綠園.
資料結構設計與C++程式應用 Fundamentals of Data Structures and Their Applications Using C++ 第3章 佇列 資料結構設計與C++程式應用.
資料結構 第5章 佇列.
鏈結串列 (Linked List).
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
2 C++ 程式概論 2.1 C++ 程式結構 程式註解 // 插入標題檔 #include 2-3
列舉(enum).
【變數與記憶體位址】 變數(Variable)提供一個有名稱的記憶體儲存空間。一個變數包含資料型態、變數本身的值及它的位址值。
C 程式設計— 指標.
String C語言-字串.
结构体和共用体 2 梁春燕 华电信息管理教研室.
101北一女中 資訊選手培訓營 妳不可不了解的指標 Nan.
STRUCTURE 授課:ANT 日期:2010/5/12.
第十五章 Linked List, Stack and Queue
C語言簡介 日期 : 2018/12/2.
第12章 從C到C++語言 12-1 C++語言的基礎 12-2 C++語言的輸出與輸入 12-3 C++語言的動態記憶體配置
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
C语言程序设计 李祥.
Chapter 7 指標.
(Circular Linked Lists)
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
4.1 單向鏈結串列 4.2 堆疊的加入與刪除 4.3 佇列的加入與刪除 4.4 其他型式的佇列
第3章 指標與字串 (Pointers and Strings)
Java 程式設計 講師:FrankLin.
JAVA 程式設計與資料結構 第四章 陣列、字串與數學物件.
Chap3 Linked List 鏈結串列.
第一單元 建立java 程式.
Chapter 5 複合資料型態.
陣列(Array).
C++ 程式設計 基礎篇 張啟中 Chang Chi-Chung.
資料結構 優點 缺點 1 陣列 (Array) 沒有額外變量 (例head, next,...) 運作/操作較簡單 更新資料時,若要保持順序,需要移動較大量資料 靜態結構Static (宣告時已決定了陣列元素多少,不能在程式執行期間增減元素) 2 隊列Queue (FIFO) 容易更新 加入enqueue:
自我參考結構 (self-reference – 1)
輸入&輸出 函數 P20~P21.
第十章 指標.
第7章 指標 7-1 指標的基礎 7-2 指標變數的使用 7-3 指標運算 7-4 指標與陣列 7-5 指向函數的指標.
挑戰C++程式語言 ──第8章 進一步談字元與字串
第11章 從C到C++語言 11-1 C++語言的基礎 11-2 C++語言的資料型態與運算子 11-3 C++語言的輸出與輸入
第三章 数据抽象.
C qsort.
第二章 类型、对象、运算符和表达式.
第14章 結構與其他資料形式.
C/C++基礎程式設計班 C++: 物件的使用、參考、重載函式 講師:林業峻 CSIE, NTU 3/28, 2015.
陣列與結構.
北一女中 資訊選手培訓營 妳不可不了解的指標 Nan.
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
結構、檔案處理(Structure, File)
第四章 陣列、指標與參考 4-1 物件陣列 4-2 使用物件指標 4-3 this指標 4-4 new 與 delete
C/C++基礎程式設計班 C語言入門、變數、基本處理與輸入輸出 講師:林業峻 CSIE, NTU 3/7, 2015.
Programming & Language Telling the computer what to do
第9章 C++程序设计初步 9.1 C++的特点 9.2 最简单的C++程序 9.3 C++的输入输出 9.4 函数的重载
變數與資料型態  綠園.
Array(陣列) Anny
C語言程式設計 老師:謝孟諺 助教:楊斯竣.
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
鏈結串列 (Linked List).
InputStreamReader Console Scanner
C++语言程序设计 C++语言程序设计 第二章 基本数据类型与表达式 第十一组 C++语言程序设计.
Presentation transcript:

指標、串列 (Linked List)

使用malloc()或calloc()配置動態記憶體 變數指標 = malloc(sizeof 資料型態); 例 int num = 100; int *numPtr = # //*numPtr指向num變數 int *newPtr; //宣告指標變數 newPtr = malloc(sizeof int); //配置動態指標變數 *newPtr = 200; //起始指標變數值=200 int *ptr1 = (int *)malloc(10*sizeof(int); int *ptr2 = (int *)calloc(10, sizeof(int))

/* Program -- malloc-example.c */ #include <stdio.h> #include <stdlib.h> /* for malloc() */ int main() { int num, i, *ptr, sum = 0; printf("將動態配置陣列,陣列內的元素個數?"); scanf("%d", &num); ptr = (int*)malloc(num*sizeof(int)); //ptr = (int*)calloc(num, sizeof(int)); //calloc()將把空間清除為0 if (ptr == NULL) { printf("無法配置足夠的記憶體,sorry! 程式關閉"); exit(0); } printf("\n從鍵盤輸入每一筆元素內容,鍵入整數之後按<Enter>鍵繼續\n\n"); for (i = 0; i < num; ++i) { printf("輸入值--> "); scanf("%d", &ptr[i]); sum += ptr[i]; //scanf("%d", ptr + i); //sum += *(ptr + i); printf("\n陣列中的元素總和 = %d", sum); free(ptr); return 0;

malloc()配置的記憶體空間指定給指標變數 char *pc = (char *)malloc(sizeof char); int *pi = (int *)malloc(sizeof int); float *px = (float *)malloc(sizeof(float)); pc A008 (沒有名稱) A308 A309 A30A A30B A008 pi A000 (沒有名稱) A300 A301 A302 A303 A000 A001 A002 A003 px A004 (沒有名稱) A304 A305 A306 A307 A004 A005 A006 A007

存取指標變數與目的內容 pc pi px *pc = ‘y’; *pi = 2518; *px = 2.7182; A008 ‘y’ (沒有名稱) A308 A309 A30A A30B A008 pi A000 2518 (沒有名稱) A300 A301 A302 A303 A000 A001 A002 A003 px A004 2.7182 (沒有名稱) A304 A305 A306 A307 A004 A005 A006 A007

free 敘述 pc pi px free(pc); free(pi); free(px); A008 ‘y’ A000 2518 A004 A30B A008 pi A000 2518 A300 A301 A302 A303 A000 A001 A002 A003 px A004 2.7182 A304 A305 A306 A307 A004 A005 A006 A007

30 50 觀念釐清 (1/3) pi pj int *pi = (int *)malloc(sizeof int); int *pj = (int *)malloc(sizeof int); *pi = 30; *pj = 50; 30 pi pj 50

觀念釐清 (2/3) *pj = *pi; 30 pi pj 30

觀念釐清 (3/3) pj = pi; 30 pi pj 50 因為失去指標的指向,這4個 bytes 的資料,無法存取,也不能刪除

泛型指標(Generic Pointer) 「泛型指標」不侷限於特定的資料型態,可指向任何資料型態的記憶體空間,具彈性,例: int x; void∗ p = &x; /∗ 指向x的整數儲存空間 ∗/ float f; p = &f; /∗指向f的浮點數儲存空間 ∗/ 泛型指標無法直接依址取值(dereference),須作指定適當的資料型態,用以轉換(typecasting)或解讀資料的意義 void∗ p; printf (“%d”,∗p); /∗ 不對的寫法 ∗/ void∗ p; int ∗px=(int∗)p; printf (“%d”,∗px); /∗ 正確 ∗/

https://goo.gl/c4R3Q2

陣列的起始位址 陣列的起始位址也是整個陣列的指標 陣列 x[]的起始位址,就是陣列第一個元素的位址 &x[0] 在C/C++中,陣列名稱單獨出現時,也代表陣列的起始位址,因此,x 也是陣列的起始位址 x 和&x[0]的意義相同

如果 x 是陣列的起始位址(也就是整個陣列的指標),那 x+1 的意義為何? 指標(位址)的加法 如果 x 是陣列的起始位址(也就是整個陣列的指標),那 x+1 的意義為何? 在C/C++中,陣列的指標加1,不是單純的只是將 x 中所存的位址值加1,實際上是加上每一個陣列元素所使用記憶體 byte 數 如果是整數或浮點數則加 4 如果是字元則加 1 若 x 是一陣列的起始位址 x 是 x[0]的位址 (即&x[0]) x+1 是 x[1]的位址 (即&x[1]) x+2 是 x[2]的位址 (即&x[2]) . . . x+n 是 x[n]的位址 (即&x[n])

指標的目的物與陣列元素 如果 x 是一陣列的起始位址 另例 *x 就是 x[0] *(x+1)就是 x[1] *(x+2)就是 x[2] . . . *(x+n)就是 x[n] 另例 short array[] = {30, 47, 26, 17, 22, 23}; //宣告字串變數 short *arrayPtr = array; //指標=array起始位址 printf("array 的第0個元素=%d“, *arrayPtr); //輸出第0元素=30 printf("array 的第1個元素=%d", *(arrayPtr+=1)); //輸出第1元素=47 printf("array 的第4個元素=%d", *(arrayPtr+=3)); //輸出第4元素=22

字元陣列與字元指標參數 在函式的參數中, 字元陣列參數 char s[] 與 字元指標參數 char *s 都是接受傳入的陣列起始位址, 兩者意義相同

但是在字串的定義與初值設定上,以字元陣列和字元指標,兩者的意義略有不同 字元陣列的定義: 以字元陣列定義字串 但是在字串的定義與初值設定上,以字元陣列和字元指標,兩者的意義略有不同 字元陣列的定義: char s[] = “apple”; 位址 &S[0] &S[1] &S[2] &S[3] &S[4] &S[5] S ‘a’ ‘p’ ‘p’ ‘l’ ‘e’ ‘\0’ S[0] S[1] S[2] S[3] S[4] S[5]

字元指標不僅可以指向單一字元,也可以指向字元陣列(字串) 字元指標的定義: 以字元指標定義字串 字元指標不僅可以指向單一字元,也可以指向字元陣列(字串) 字元指標的定義: char *t = “apple”; t t+0 t+1 t+2 t+3 t+4 t+5 位址 ‘a’ ‘p’ ‘p’ ‘l’ ‘e’ ‘\0’ *(t+0) *(t+2) *(t+4) *(t+1) *(t+3) *(t+5)

以字元陣列的起始位址 s,或是以指標 t 都可以代表字串 下列兩個敘述,都可以印出字串內容 兩者的相同點 以字元陣列的起始位址 s,或是以指標 t 都可以代表字串 下列兩個敘述,都可以印出字串內容 cout << s; cout << t;

兩者的差異 字元陣列可以直接儲存字串 字元指標必須另有初值設定或是以malloc()配置記憶體,才能儲存字串 字串陣列的名稱是一個常數 char s[10]; scanf(“%s”, s); 字元指標必須另有初值設定或是以malloc()配置記憶體,才能儲存字串 char *t; t = malloc(10); scanf(“%s”, t); 字串陣列的名稱是一個常數 s+3; 合法敘述 s++; 不合法敘述 字元指標的名稱是一個變數 t+3; 合法敘述 t++; 合法敘述

x 是整個陣列的起始位址 (即&x[0][0]) 指標與二維陣列 宣告二維陣列範例:int x[3][2]; x 是整個陣列的起始位址 (即&x[0][0]) x[0], x[1], x[2] 分別是第一、二、三列的起始位址 (即 &x[0][0], &x[1][0], &x[2][0]) x[0] x[0][0] x[0][1] x[1] x[1][0] x[1][1] x[2] x[2][0] x[2][1]

sizeof array / sizeof array[0] 範例 長度運算符號 sizeof 變數名稱 sizeof array / sizeof array[0] 範例 printf(“%d”, sizeof(int)); //輸出int型態的長度4 printf(“%d”, sizeof(float)); //輸出float型態的長度4 printf(“%d”, sizeof(double)); //輸出double型態的長度8 char *array[] = {"床前明月光,", "疑似地上霜;", "舉頭望明月,", "低頭思故鄉。" }; //宣告陣列指標 int count = (sizeof array)/(sizeof array[0]); //計算元素個數

字元指標 (1/2) char* 字元指標名稱 = "字串資料"; char string[ ] = "ANSI/ISO C++"; //string為字串變數 char *pstring = "Visual C++"; //pstring為字串指標 printf(“%s”, string); //顯示字串變數值 printf(“%s”, pstring); //顯示指標位址到字串結束 printf(“%c”, string[7]); //顯示字串第7元素值 printf(“%s”, pstring + 7); //顯示指標第7元素至結束

字元指標 (2/2) 範例 char array[4][] = { "床前明月光", "疑似地上霜", "舉頭望明月", "低頭思故鄉" }; //宣告二維字串陣列 char *parray [4] = { "床前明月光", "低頭思故鄉" }; //宣告一維字串指標

傳遞常數指標 (1/2) 範例 void main(void) { const int LEN = 5; //宣告整常數符號 void power(const int *); //計算平方函數原型 void main(void) { const int LEN = 5; //宣告整常數符號 power(&LEN); //傳遞常數指標 } void power(const int *NUM) //計算平方函數 cout << (*NUM) * (*NUM);

傳遞常數指標 (2/2) 範例二 int main() { int LEN = 5; //宣告整整數變數 void power(const int *); //計算平方函數原型 int main() { int LEN = 5; //宣告整整數變數 power(&LEN); //傳指呼叫, 傳遞變數位址 } void power(const int *NUM) //接收指標常數 cout << *NUM * *NUM;

傳回函數指標 範例 int main() { cout << *getNumber(); //取得getNumber()指標值 } float *getNumber() //輸入浮點數函數 float *num = (float *)malloc(sizeof float); cin >> *num; return num;

指標與結構綜合應用: 以Linked List為例

利用malloc()配置記憶體給一個結構指標 配置記憶體給結構指標 利用malloc()配置記憶體給一個結構指標 typedef struct { char name[10]; int age; char sex; } person; struct person *p; p = (person *)malloc(sizeof person); p age name sex

鍊結串列(Linked List) 利用指標,將許多個結構串接在一起 每一個結構體稱為一個“節點” 建立鍊結串列是將節點逐一加入 p null

鍊結串列相較於陣列的優缺點 優點 (鍊結串列優於陣列之處): 缺點 (鍊結串列不及陣列之處): 依照實際資料個數來動態配置記憶體 每個節點可以依照需求,加入任意位置 缺點 (鍊結串列不及陣列之處): 每個節點都需要有一個指標變數 存取速度較慢

鍊結串列節點的結構 「節點」的結構至少需包括 兩個欄位 data next 資料欄位,存放資料 指標欄位,用於指向下一個節點 struct node //結構的名稱為 node { int data; //存放資料 struct node *next; //存放下一節點的指標 }; data next

「堆疊」是一種常見的資料結 構,可使用鍊結串列加以實作 鍊結串列應用 -- 堆疊 (Stack) 「堆疊」是一種常見的資料結 構,可使用鍊結串列加以實作 後進先出(last-in first-out): 節點從頂端 top 加入,也從頂端刪除 top 指標指向堆疊的頂端 p指標指向擬加入之新節點 top null p top null

定義top指標(全域變數),指向堆疊頂端 實作堆疊 宣告一個節點的結構 struct node struct node { int data; struct node *next; }; 定義top指標(全域變數),指向堆疊頂端 struct node *top; data next top

堆疊初始化 -- InitStack() void InitStack() { top = NULL; } top null

加入節點 -- PushStack() top null p top null p void PushStack(int value) { struct node *p; p = new struct node; p->data = value;//與(*p).data = value等義 p->next = top; top = p; } top null p top null p

移除節點 -- PopStack() top null p top null p int PopStack() { struct node *p; int value; p = top; top = top->next; value = p->data; // p = p->data ?? delete p; return (value); } top null p top null p

使用鍊結串列實作「佇列」(queue)資料結構 先進先出(first-in first-out) Enqueue()與Dequeue()函式 延伸思考 使用鍊結串列實作「佇列」(queue)資料結構 先進先出(first-in first-out) Enqueue()與Dequeue()函式 一般形式 http://bit.ly/2fPs7zs http://bit.ly/2AjT1IW 變形:環狀佇列 配置固定大小的空間將結構的首尾相連,Front和Back分別指示讀出與寫入資料的位置,簡化運作