Data Structures Chapter 4 Linked Lists Instructor: Ching Chi Lin 林 清 池 助 理 教 授 chingchi.lin@gmail.com Department of Computer Science and Engineering National Taiwan Ocean University
Outline Singly Linked Lists and Chains ( 單 向 鏈 結 串 列 與 鏈 ) Representing Chains in C ( 用 C 語 言 來 表 示 鏈 ) Linked Stacks and Queues ( 鏈 結 堆 疊 與 鏈 結 佇 列 ) Polynomials ( 多 項 式 ) Additional List Operations ( 更 多 的 串 列 運 算 ) Equivalence Classes ( 等 價 關 係 ) Sparse Matrices ( 稀 疏 矩 陣 ) Doubly Linked Lists ( 雙 向 鏈 結 串 列 ) 2
Singly Linked Lists and Chains 1/4 ( 單 向 鏈 結 串 列 與 鏈 ) We studied the representation of simple data structures using an array and a sequential mapping. ( 我 們 已 學 習 使 用 陣 列 和 循 序 映 射 的 簡 易 資 料 結 構 ) These representations had the property that successive nodes of the data object were stored a fixed distance. ( 連 續 的 資 料 物 件 以 相 等 距 離 的 節 點 來 儲 存 ) Problems: When a sequential mapping is used for ordered lists: No more storage available. ( 沒 有 可 用 的 空 間 ) We could waste storage. ( 浪 費 空 間 ) Excessive data movement is required for deletions and insertions. ( 在 插 入 及 刪 除 的 過 程 中, 會 需 要 大 量 的 資 料 搬 遷 ) 3
Singly Linked Lists and Chains 2/4 ( 單 向 鏈 結 串 列 與 鏈 ) Original BAT CAT FAT HAT JAT Insert EAT after CAT: move 3elements BAT CAT EAT FAT HAT JAT Delete EAT : move 3elements BAT CAT FAT HAT JAT 4
Singly Linked Lists and Chains 3/4 ( 單 向 鏈 結 串 列 與 鏈 ) Solution: using linked representation BAT CAT EAT FAT HAT A linked list is comprised of nodes; each node has zero or more data fields and one or more link or pointer fields. ( 鏈 結 串 列 由 節 點 組 成, 每 一 個 節 點 包 含 資 料 項 及 指 標 項 ) The nodes may be placed anywhere in memory. ( 節 點 可 放 置 在 記 憶 體 的 任 何 位 子 ) With each node we store the address of location of the next node in the list. ( 每 一 節 點 紀 錄 著 下 一 節 點 的 位 置 ) 5
Singly Linked Lists and Chains 4/4 ( 單 向 鏈 結 串 列 與 鏈 ) In a singly linked list, each node has exactly one pointer field. ( 在 單 向 鏈 結 串 列 裡, 每 一 個 節 點 恰 有 一 個 指 標 項 ) A singly linked list in which the last node has a null link is called a chain ( 如 果 一 個 單 向 鏈 結 串 列 的 最 後 一 個 節 點 的 指 標 指 向, 我 們 稱 這 個 鏈 結 串 列 為 鍊 ) BAT CAT EAT FAT HAT 6
Functions of Linked List 1/2 Insert Step 1: Get a node a that is currently unused. Step 2: Set the data field of a to EAT. Step 3: Set the link field of a to the node after CAT, which contains FAT. Step 4: Set the link field of the node containing CAT to a. BAT CAT FAT HAT JAT BAT CAT FAT HAT JAT Step 4 EAT Step 3 7
Functions of Linked List 2/2 Delete We only need to find the element that immediately precedes EAT, which is CAT, and set its link field to point to EAT s link. ( 只 需 要 找 出 EAT 的 前 一 項, 將 前 一 項 的 指 標 指 到 EAT 所 指 到 的 節 點 ) We have not moved any data, although the link field of EAT still points to FAT, EAT is no longer in the list. ( 不 需 要 宜 除 任 何 資 料, 雖 然 EAT 的 指 標 仍 然 指 向 指 向 FAT, 但 EAT 已 不 在 串 列 中 ) BAT CAT EAT FAT HAT JAT 8
Outline Singly Linked Lists and Chains ( 單 向 鏈 結 串 列 與 鏈 ) Representing Chains in C ( 用 C 語 言 來 表 示 鏈 ) Linked Stacks and Queues ( 鏈 結 堆 疊 與 鏈 結 佇 列 ) Polynomials ( 多 項 式 ) Additional List Operations ( 更 多 的 串 列 運 算 ) Equivalence Classes ( 等 價 關 係 ) Sparse Matrices ( 稀 疏 矩 陣 ) Doubly Linked Lists ( 雙 向 鏈 結 串 列 ) 9
Pointers C provides extensive supports for pointers. Any type T in C there is a corresponding type pointer to T. ( 在 C 程 式 語 言 中 的 任 何 資 料 型 態, 都 有 其 相 對 應 的 指 標 ) The two most important operators used with the pointer type are: & the address operator * the dereferencing (indirection) operator Example: int i, *pi; i is an integer variable and pi is a pointer to an integer. pi = &i; &i returns the address of i and assigns it as the value of pi. i = 10; or *pi = 10; to assign a value to i if (pi == ) or if (!pi); to test if the pointer is null. 10
Pointers Can Be Dangerous 1/2 Using pointers: high degree of flexibility and efficiency, but dangerous as well. ( 使 用 指 標 雖 然 可 以 獲 得 高 度 彈 性 與 效 率, 但 指 標 也 可 能 是 危 險 的 ) It is a wise practice to set all pointers to when they are not actually pointing to an object. ( 將 沒 有 實 際 指 向 物 件 的 所 有 指 標 設 定 為 ) Using explicit type cast when converting between pointer types. ( 在 指 標 型 態 轉 換 時, 使 用 明 確 的 type cast.) Example: pi = malloc(sizeof(int)); /*assign to pi a pointer to int*/ pf = (float *)pi; /*casts an int pointer to a float pointer*/ 11
Pointers Can Be Dangerous 2/2 In many systems, pointers have the same size as type int. ( 在 許 多 系 統 中, 指 標 的 大 小 和 int 型 態 的 大 小 相 同 ) Since int is the default type specifier, some programmers omit the return type when defining a function. ( 由 於 int 為 預 設 函 數 型 態, 一 些 程 式 設 計 師 定 義 函 數 時 省 略 了 傳 回 型 態 ) The return type defaults to int which can later be interpreted as a pointer. ( 預 設 為 int 的 傳 回 型 態 可 被 解 釋 為 一 個 指 標 ) The programmer is urged to define explicit return for functions. ( 程 式 人 員 被 要 求 應 為 函 數 定 義 明 確 的 傳 回 型 態 ) 12
Using Dynamically Allocated Storage C provides a mechanism, called heap, for allocating storage at run time. (C 提 供 一 種 機 制, 稱 之 為 heap, 使 我 們 可 以 在 執 行 時 期 配 置 記 憶 體 ) malloc: a function provided in C for performing dynamic memory allocation. free: a function provided in C for returning the area of memory to the system. Example: 13
Example 4.1: List of words The following declarations contain an example of selfreferential structure. ( 以 下 為 一 個 自 身 參 考 結 構 的 範 例 ) C allows us to create a pointer to a type that does not yet exist. (C 允 許 我 們 建 立 指 向 尚 未 存 在 的 型 態 指 標 ) typedef struct list_node *list_pointer; typedef struct list_node{ char data[4]; list_pointer link; To create a new empty list: list_pointer first = ; To define an IS_EMPTY macro to test for an empty list: #define IS_EMPTY (first) (!(first)) 14
Example 4.1: List of words To obtain a new node: first = (list_pointer) malloc(sizeof(list_node)); To place the word BAT into our list: strcpy (first data, BAT ); first link =; If e is a pointer to a structure, then e name is equal to (*e).name first B A T \0 15 first data[0] first data[1] first data[2] first link first data[3]
Program 4.1:Create a two node list Two node linked list list_pointer create2() { /* create a linked list with two nodes */ list_pointer first, second; first = (list_pointer)malloc(sizeof(list_node)); second = (list_pointer)malloc(sizeof(list_node)); second link = ; second data = 20; first data = 10; first link = second; return first; typedef struct list_node *list_pointer; typedef struct list_node { int data; list_pointer link; ; first 10 20 16
Program 4.2:Simple insert into front of list List insertion void insert(list_pointer *first, list_ointer x) { /* insert a new node with data = 50 into the chain first after node x */ list_pointer temp; temp = (list_poitner)malloc(sizeof(list_node)); if(is_full(temp)){ fprintf(stderr, The memory is full\n ); exit(1); temp >data = 50; if(*first) { temp link = x link; node link = temp; else { temp link = ; *first = temp; Function call: insert(&first, x); 17 Case 1:a nonempty list *first Case 2:an empty list *first temp x : points to the node that precedes the new node we wish to insert. 50 x 50
Program 4.3: Deletion from a list void delete(list_pointer *first, list_pointer trail, list_pointer x) { /* delete x from the list, trail is the preceding node and *first is the front of the list */ if(trail) trail link = x link; else *first = (*first) link; free(x); Function call: delete(&first, trail, trail link); x : points to the node that we wish to delete trail: points to the node that precedes x Function call: delete(&first,, first); Case 1: trail x Case 2: trail = *first, trail 10 50 20 *first, x 10 50 20 18
Program 4.4:Printing a list Printing out a list void print_list(list_pointer first) { printf( The list contains: ); for (; first; first = first link) printf( %4d, first data); printf( \n ); first 10 50 20 19
Outline Singly Linked Lists and Chains ( 單 向 鏈 結 串 列 與 鏈 ) Representing Chains in C ( 用 C 語 言 來 表 示 鏈 ) Linked Stacks and Queues ( 鏈 結 堆 疊 與 鏈 結 佇 列 ) Polynomials ( 多 項 式 ) Additional List Operations ( 更 多 的 串 列 運 算 ) Equivalence Classes ( 等 價 關 係 ) Sparse Matrices ( 稀 疏 矩 陣 ) Doubly Linked Lists ( 雙 向 鏈 結 串 列 ) 20
Linked Stack and Queue The direction of links for both stack and the queue facilitate easy insertion and deletion of nodes. ( 鏈 結 的 方 向 使 得 插 入 和 刪 除 節 點 更 容 易 進 行 ) Easily add or delete a node form the top of the stack. Easily add a node to the rear of the queue and delete a node at the front of a queue. top (a) Linked stack front (b) Linked queue data link data link rear 21
Declarations and The Initial Condition for Stacks The declarations #define MAX_STACKS 10 /*maximum number of stacks */ typedef struct{ int key; /*other fields */ element; typedef struct stack *stack_pointer; typedef struct stack{ element data; stack_pointer link; ; stack_pointer top[max_stacks]; The initial condition top[i] =, 0 i < MAX_STACKS; 22
Program 4.5 : Add to A Linked Stack void push(stack_pointer *top, element item) { /* add an item to the top of the stack */ stack_pointer temp = (stack_pointer) malloc(sizeof(stack)); if(is_full(temp)) { fprintf(stderr, The memory is full\n ); exit(1); temp data = item; temp link = *top; *top = temp; temp *top 23
Program 4.6 : Delete from A Linked Stack element pop(stack_pointer *top) { /* remove top element from the stack */ stack_pointer temp = *top; element item; if (IS_EMPTY(temp)) { fprintf(stderr, The stack is empty\n ); exit(1); item = temp data; *top = temp link; free(temp); return item; temp *top 24
Declarations and The Initial Condition for Queues The declarations #define MAX_QUEUES 10 /*maximum number of queues */ typedef struct queue *queue_pointer; typedef struct queue { element data; queue_pointer link; ; queue_pointer front[max_queues], rear[max_queues]; The initial condition front[i] =, 0 i < MAX_QUEUES; 25
Program 4.7 : Add to The Rear of a Linked Queue 26 void addq(queue_pointer *front, queue_pointer *rear, element item) { /*add an element to the rear of the queue*/ queue_pointer temp = (queue_pointer) malloc(sizeof(queue)); if (IS_FULL(temp)) { fprintf(stderr, The memory is full\n ); exit(1); Case 1: *front *front *rear temp data = item; temp link = ; if (*front) (*rear) link = temp; else *front = temp; Case 2: *front = *rear = temp; temp *front *rear temp
Program 4.8 : Delete From the Front of a Linked Queue element deleteq(queue_pointer *front) { /* delete an element from the queue */ queue_pointer temp = *front; element item; if (IS_EMPTY(*front)) { fprintf(stderr, The queue is empty\n ); exit(1); item = temp data; *front = temp link; free(temp); *front return item; temp rear 27
Outline Singly Linked Lists and Chains ( 單 向 鏈 結 串 列 與 鏈 ) Representing Chains in C ( 用 C 語 言 來 表 示 鏈 ) Linked Stacks and Queues ( 鏈 結 堆 疊 與 鏈 結 佇 列 ) Polynomials ( 多 項 式 ) Additional List Operations ( 更 多 的 串 列 運 算 ) Equivalence Classes ( 等 價 關 係 ) Sparse Matrices ( 稀 疏 矩 陣 ) Doubly Linked Lists ( 雙 向 鏈 結 串 列 ) 28
Polynomial Representation We want to represent the polynomial : We will represent each term as a node containing coefficient and exponent fields, as well as a pointer to the next term. Declarations: em 1 A( x) = a x + L+ m 1 a 0 x e 0 typedef struct poly_node *poly_pointer; typedef struct poly_node { int coef; int expon; poly_pointer link; ; coef expon link poly_node 29
Figure 4.12 Examples: a = 3x 14 + 2x 8 + 1 a 3 14 2 8 1 0 b = 8x 14 3x 10 + 10x 6 b 8 14 3 10 10 6 30
Generating The First Three Terms of c = a + b 1/3 a 3 14 2 8 1 0 b 8 14 3 10 10 6 c 11 14 (1) a expon == b expon 31
Generating The First Three Terms of c = a + b 2/3 a 3 14 2 8 1 0 b 8 14 3 10 10 6 c 11 14 3 10 (2) a expon < b expon 32
Generating The First Three Terms of c = a + b 2/3 a 3 14 2 8 1 0 b 8 14 3 10 10 6 c 11 14 3 10 2 8 (3) a expon > b expon 33
Program 4.9 : Add Two Polynomials 1/2 34 poly_pointer padd(poly_pointer a, poly_pointer b) { /* return a polynomial which is the sum of a and b */ poly_pointer front, rear, temp; int sum; rear = (poly_pointer)malloc(sizeof(poly_node)); if (IS_FULL(rear)){ fprintf(stderr, The memory is full\n ); exit(1) front = rear; while (a && b) switch (COMPARE(a expon, b expon)) { case 1: /* a >expon < b >expon */ attach(b coef, b expon, &rear); b = b link; break;
Program 4.9 : Add Two Polynomials 2/2 case 0: /* a expon = b expon */ sum = a coef + b coef; if (sum) attach(sum, a >expon, &rear); a = a link; b = b link; break; case 1: /* a expon > b expon */ attach(a coef, a expon, &rear); a = a link; /* copy rest of list a and then list b*/ for (; a; a = a link) attach(a coef, a expon, &rear); for (; b; b = b link) attach(b coef, b expon, &rear); rear >link = : /* delete extra initial node */ temp = front; front = front link; free(temp); return front; 35
Program 4.10 : Attach A Node to The End of A List void attach(float coefficient, int exponent, poly_pointer *ptr) { /* create a new node with coef = coefficient and expon = exponent, attach it to the node pointed to by ptr. Ptr is updated to point to this new node */ poly_pointer temp; temp = (poly_pointer)mallc(sizeof(poly_node)); if (IS_FULL(temp)) { fprintf(stderr, The memory is full\n ); exit(1); temp coef = coefficient; temp expon = exponent; (*ptr) link = temp; *ptr = temp; 36
Analysis of padd Assume that a and b have m and n terms, respectively. A( x) e 1 e0 f 1 a x m n = + L+ a x and B( x = b x + L + m 1 0 ) n 1 b 0 x f 0 There are three cost measures: coefficient additions 0 number of coefficient additions min{m, n exponent comparisons On each iteration, either a or b or both move to the next term. The maximum number of exponent comparisons is m + n. create of new nodes for c The maximum number of terms in c is m + n. Therefore, the computing time is O(m + n). 37
Erasing Polynomials Read in polynomials a, b and d and then compute e = a * b + d. poly_pointer a, b, d, e... a = read_poly( ); b = read_poly( ); d = read_poly( ); temp = pmult(a, b); e = padd(temp,d); print_poly(e); We created temp only to hold a partial result for d. ( 一 些 節 點 是 為 保 存 部 分 結 果 而 建 立 ) By returning the nodes of temp, we may use them to hold other polynomials. ( 將 節 點 釋 放 回 去 之 前, 我 們 可 以 用 它 們 來 儲 存 其 他 多 項 式 ) 38
Program 4.11: Erasing a polynomial One by one, erase frees the nodes in temp. void erase(poly_pointer *ptr) { /* erase the polynomial pointed to by ptr */ poly_pointer temp; while (*ptr) { temp = *ptr; *ptr = (*ptr) link; free(temp); Can we free all the nodes of a polynomial more efficiently? 39
Circular List Representation of Polynomials A singly linked list in which the link field of the last node points to the first node is called a circular list. ( 如 果 一 個 單 向 鏈 結 串 列 的 最 後 一 個 節 點 的 指 標 指 向 第 一 個 節 點, 我 們 稱 這 個 鏈 結 串 列 為 環 狀 鏈 結 串 列 ) Circular representation of 3x 14 + 2x 8 + 1 3 14 2 8 1 0 last In order to obtain an efficient erase algorithm, we maintain our own list of nodes that have been freed. ( 為 了 得 到 有 效 率 的 演 算 法, 我 們 建 立 一 個 串 列 將 已 經 釋 放 的 節 點 儲 存 起 來 ) Only when the list is empty do we need to use malloc to create a new node. ( 只 有 在 list 是 空 的 時 候, 我 們 使 用 malloc 去 建 立 一 個 新 節 點 ) 40
Functions for Representation of Polynomials Let avail be a variable of type poly_pointer that points to the first node in our list of freed nodes. (avail 指 向 釋 放 的 串 列 的 第 一 個 ) Instead of using malloc and free, we now use get_node and ret_node. ( 相 對 於 malloc 和 free, 我 們 現 在 使 用 get_node 和 ret_node) To avoid the special case of zero polynomials, we introduce a header node into each polynomial. ( 為 了 處 理 一 些 特 別 情 況, 我 們 在 每 一 個 多 項 式 中 加 入 header node ) Each polynomial, zero or nonzero, contains one additional node. avail list of freed nodes 41
Example Polynomials with header nodes header (a) Zero polynomial header 3 14 2 8 1 0 (b) 3x 14 + 2x 8 + 1
Program 4.12 : get_node function 43 poly_pointer get_node(void) { /* provide a node for use */ poly_pointer node; if (avail) { node = avail; avail = avail link; else { node = (poly_pointer) malloc(sizeof(poly_node)); if (IS_FULL(node)) { fprintf(stderr, The memory is full\n ); exit(1); return node; 2 node 1 avail
Program 4.13 : ret_node function void ret_node(poly_pointer ptr) { /* return a node to the available list */ ptr link = avail; avail = ptr; ptr 2 1 avail 44
Program 4.14 : Erasing a circular list void cerase(poly_pointer *ptr) { /*erase the circular list ptr */ poly_poitner temp; if (*ptr) { temp = (*ptr) link; (*ptr) link = avail; avail = temp; *ptr = ; prt 3 2 temp 1 avail 45
Outline Singly Linked Lists and Chains ( 單 向 鏈 結 串 列 與 鏈 ) Representing Chains in C ( 用 C 語 言 來 表 示 鏈 ) Linked Stacks and Queues ( 鏈 結 堆 疊 與 鏈 結 佇 列 ) Polynomials ( 多 項 式 ) Additional List Operations ( 更 多 的 串 列 運 算 ) Equivalence Classes ( 等 價 關 係 ) Sparse Matrices ( 稀 疏 矩 陣 ) Doubly Linked Lists ( 雙 向 鏈 結 串 列 ) 46
Additional List Operations A singly linked list in which the last node has a null link is called a chain. Operations: Invert a chain Concatenate two chains ptr A singly linked list in which the link field of the last node points to the first node is called a circular list. Operations: Insert a node at the front of a circular list Determine the length of a circular list prt 47
Program 4.16:Inverting a singly linked list List_pointer invert (list_pointer lead) { /* invert the list pointed to by lead */ listpointer middle, trail; middle = ; while(lead){ trail = middle; middle = lead; lead = lead link; middle link = trail; return middle; lead lead 48
Program 4.17: Concatenating singly linked lists list_pointer concatenate (list_pointer ptr1, list_pointer ptr2) { /* produce a new list that contains the list ptr1 followed by the list ptr2. The list pointed to by ptr1 is changed permanently */ /* check for empty lists */ if (!ptr1) return ptr2; ptr1 if (!ptr2) return ptr1; /* neither list is empty, find end of first list */ for(temp = ptr1; temp link; temp = temp link); /* linked end of first to start of second */ temp link = ptr2; ptr2 49
Program 4.18 : Inserting at the front of a list void insert_front(list_pointer *last, list_pointer node) { /* insert node at the front of the circular list whose last node is last */ if (!(*last)){ /* list is empty, change last to point to new entry */ *last = node; node link = node; else{ /* list is not empty, add new entry at front node link = (*last) link; (*last) link = node; 1 *last 1 2 node *last 2 50
Program 4.19 : Finding the length of a circular list int length(list_pointer last) { /* find the length of circular list last */ list_pointer temp; int count = 0; if (last) { temp=last; do { count++ temp = temp link; while (temp!= last); return count; last 51
Outline Singly Linked Lists and Chains ( 單 向 鏈 結 串 列 與 鏈 ) Representing Chains in C ( 用 C 語 言 來 表 示 鏈 ) Linked Stacks and Queues ( 鏈 結 堆 疊 與 鏈 結 佇 列 ) Polynomials ( 多 項 式 ) Additional List Operations ( 更 多 的 串 列 運 算 ) Equivalence Classes ( 等 價 關 係 ) Sparse Matrices ( 稀 疏 矩 陣 ) Doubly Linked Lists ( 雙 向 鏈 結 串 列 ) 52
Sparse Matrices Representation When we performed matrix operations such as +,, or *, the number of nonzero terms varied. ( 執 行 運 算 後, 非 零 項 個 數 會 改 變 ) The sequential representation of sparse matrices suffered from the same inadequacies as the similar representation of polynomials. ( 稀 疏 矩 陣 的 循 序 表 示 和 多 項 式 循 序 表 示 有 相 同 的 缺 點 ) We use a linked list representation for sparse matrices. There are two types of nodes in the representation: header nodes and elements nodes. ( 共 有 兩 類 的 節 點, 標 頭 節 點 與 資 料 項 節 點 ) next row col value down right down right header node element node 53
Example : 4 x 5 sparse matrix 5 4 6 H0 H1 H2 H3 H4 H0 0 0 2 H1 1 0 4 1 3 3 H2 2 4 0 0 0 0 0 3 H3 3 0 8 3 3 1 0 8 0 0 0 0 0 1 H4 4 2 6 0 0 6 0 54
Sparse Matrices Representation We represent each column (row) of a sparse matrix as a circularly linked list with a header node. ( 每 一 行 ( 列 ) 都 以 環 狀 鏈 結 串 列 表 示 ) The header node for row i is also the header node for column i. The number of header nodes is max{ num_rows, num_cols. ( 列 i 的 標 頭 節 點 同 時 也 是 行 i 的 標 頭 節 點, 標 頭 節 點 的 個 數 為 max{ 列 數, 行 數 ) Each element node is simultaneously linked into two lists: a row list, and a column list. ( 每 一 個 資 料 節 點 出 現 在 兩 個 串 列 中 ) Each head node is belonged to three lists: a row list, a column list, and a header node list. ( 每 一 個 標 頭 節 點 出 現 在 三 個 串 列 中 ) next row col value down right down right header node element node 55
Outline Singly Linked Lists and Chains ( 單 向 鏈 結 串 列 與 鏈 ) Representing Chains in C ( 用 C 語 言 來 表 示 鏈 ) Linked Stacks and Queues ( 鏈 結 堆 疊 與 鏈 結 佇 列 ) Polynomials ( 多 項 式 ) Additional List Operations ( 更 多 的 串 列 運 算 ) Equivalence Classes ( 等 價 關 係 ) Sparse Matrices ( 稀 疏 矩 陣 ) Doubly Linked Lists ( 雙 向 鏈 結 串 列 ) 56
Doubly Linked Lists The Problem of a singly linked list: The only way to find the node that precedes p is to start at the beginning of the list. ( 找 p 節 點 的 前 一 節 點 的 唯 一 方 法 是 從 頭 開 始 找 ) When we have a problem in which it is necessary to move in either direction. ( 對 於 某 些 問 題, 雙 向 移 動 是 必 須 的 ) Therefore, it is useful to have doubly linked lists. declarations: typedef struct node *node_pointer; typedef struct node{ node_pointer llink; element data; node_pointer rlink; ; 57
Doubly linked circular list with header node Header node allows us to implement operations more easily. ptr = ptr llink rlink = ptr rlink llink Header Node left data right first Empty doubly linked circular list with header node 58
Program 4.26 Insertion into A Doubly Linked Circular List void dinsert(node_pointer node, node_pointer newnode) { /* insert newnode to the right of node */ newnode llink = node; newnode rlink = node rlink; node rlink llink = newnode; node rlink = newnode; node 1 4 3 2 59 newnode
Program 4.27 Deletion from A Doubly Linked Circular List void ddelete(node_pointer node, node_pointer deleted) { /* delete from the doubly linked list */ if (node == deleted) printf( Deletion of head node not permitted. \n ); else { deleted >llink >rlink = deleted >rlink; deleted >rlink >llink = deleted >llink; free(deleted); node 1 2 deleted 60
Figure 4.23 void ddelete(node_pointer node, node_pointer deleted) { /* delete from the doubly linked list */ if (node == deleted) printf( Deletion of head node not permitted. \n ); else { deleted >llink >rlink = deleted >rlink; deleted >rlink >llink = deleted >llink; free(deleted); Before front front After x x Deletion in a doubly linked list with a single node 61