链表
链表(linked list)就是一些包含数据的独立的数据结构(节点)的集合. 每个节点通过链或指针连结在一起. 程序通过指针访问链表中的节点.
单链表
在单链表中, 每个节点包含一个指向链表下一结点的指针. 链表最后一个节点的指针 字段值为 NULL.
需要使用一个根指针 (root pointer) 记住链表的起始位置.
typedef struct NODE { struct NODE *link; int value; } Node;
在单链表中插入
为了返回到上一个节点, 需要 始终保存一个指向链表当前节点之前的那个节点的指针.
#include <stdlib.h> #include <stdio.h> #define FALSE 0 #define TRUE 1 typedef struct NODE { struct NODE *link; int value; } Node; int sll_insert(Node *current, int new_value) { Node *previous; Node *new; while (current->value < new_value){ previous = current; current = current->link; } new = (Node *)malloc(sizeof(Node)); if (new == NULL) return FALSE; new->value = new_value; new->link = current; previous->link = new; return TRUE; }
这个插入函数是不正确的. while 循环会越过链表尾部, 并对一个 NULL 指针进行间接 访问操作. 改变 while 循环解决这个问题
while (current != NULL && current->value < value){
为了在链表插起始位置插入一个节点, 函数必须修改根指针. 但是函数不能访问变量 root. 我们需要就爱那个指向 root 的指针作为参数传递给函数.
#include <stdlib.h> #include <stdio.h> #define FALSE 0 #define TRUE 1 typedef struct NODE { struct NODE *link; int value; } Node; int sll_insert(Node **rootp, int new_value) { Node *current; Node *previous; Node *new; current = *rootp; while (current != NULL && current->value < new_value){ previous = current; current = current->link; } new = (Node *)malloc(sizeof(Node)); if (new == NULL) return FALSE; new->value = new_value; new->link = current; if (previous == NULL) *rootp = new; else previous->link = new; return TRUE; }
优化插入函数
/* * 插入到一个有序单链表. 函数的参数是一个指向链表第一个节点的指针, * 以及一个需要插入的新值 */ #include <stdlib.h> #include <stdio.h> #define FALSE 0 #define TRUE 1 typedef struct NODE { struct NODE *link; int value; } Node; int sll_insert(register Node **linkp, int new_value) { register Node *current; register Node *new; while ((current = *linkp) != NULL && current->value < new_value) linkp = ¤t->link; new = (Node *) malloc (sizeof(Node)); if (new == NULL) return FALSE; new->value = new_value; new->link = current; *linkp = new; return TRUE; }
双链表
双链表每个节点都包含两个指针----指向前一个节点的指针和指向后一个节点的指针. 这可以使我们以任何方向遍历双链表.
typedef struct NODE{ struct NODE *fwd; struct NODE *bwd; int value; } Node;
在双链表中插入
#include <stdlib.h> #include <stdio.h> typedef struct NODE{ struct NODE *fwd; struct NODE *bwd; int value; } Node; int dll_insert(Node *rootp, int value) { Node *this; Node *next; Node *newnode; for (this = rootp; (next = this->fwd) != NULL; this = next){ if (next->value == value) return 0; if (next->value > value) break; } newnode = (Node *) malloc (sizeof(Node)); if (newnode == NULL) return -1; newnode->value = value; if (next != NULL){ newnode->fwd = next; if (this != rootp){ this->fwd = newnode; newnode->bwd = this; } else { rootp->fwd = newnode; newnode->bwd = NULL; } next->bwd = newnode; }else{ newnode->fwd = NULL; if (this != rootp){ this->fwd = newnode; newnode->bwd = this; }else{ rootp->fwd = newnode; newnode->bwd = NULL; } rootp->bwd = newnode; } return 1; }
双链表最简版
#include <stdlib.h> #include <stdio.h> typedef struct NODE{ struct NODE *fwd; struct NODE *bwd; int value; } Node; int dll_insert(register Node *rootp, int value) { register Node *this; register Node *next; register Node *newnode; for (this = rootp; (next=this->fwd) != NULL; this=next){ if (next->value == value) return 0; if (next->value > value) break; } newnode = (Node *) malloc(sizeof(Node)); if (newnode == NULL) return -1; newnode->value = value; newnode->fwd = next; this->fwd = newnode; if (this != rootp) newnode->bwd = this; else newnode->bwd = NULL; if (next != NULL) next->bwd = newnode; else rootp->bwd = newnode; return 1; }