演算法導論 第10章 10.2 連結串列
阿新 • • 發佈:2018-12-25
一、概念
(1)陣列的線性序是由陣列的下標決定的,連結串列中的順序是由各物件中的指標所決定的 (2)連結串列結點結構 node *prev; node *next; int key; (3)連結串列結點 node *head; node *nil;//哨兵 (4)對連結串列的操作 LIST-SEARCH(L, k) LIST-INSERT(L, x) LIST-DELETE(L, x) (5)哨兵是個啞物件,可以簡化邊界條件二、程式碼
(1)沒有哨兵的情況
//連結串列結點結構 struct node { node *pre; node *next; int key; //建構函式 node(int x):pre(NULL),next(NULL),key(x){} }; //連結串列結構 struct List { node *head; List():head(NULL){} }; //列印 void List_Print(List *L) { node *p = L->head; while(p) { cout<<p->key<<' '; p = p->next; } cout<<endl; } //搜尋,找出L中第一個關鍵字為k的結點,沒有則返回NULL node *List_Search(List *L, int k) { node *x = L->head; while(x != NULL && x->key!=k) x = x->next; return x; } //插入 void List_Insert(List *L, node *x) { //插入到表的前端 x->next = L->head; if(L->head != NULL) L->head->pre = x; L->head = x; x->pre = NULL; } //刪除 void List_Delete(List *L, node* x) { if(x->pre != NULL) x->pre->next = x->next; else L->head = x->next; if(x->next != NULL) x->next->pre = x->pre; delete x; }
(2)有哨兵的情況
//連結串列結點結構 struct node { node *pre; node *next; int key; //建構函式 node(int x):pre(NULL),next(NULL),key(x){} }; //連結串列結構 struct List { node *nil;//哨兵 List() { nil = new node(0); nil->next = nil; nil->pre = nil; } }; //列印 void List_Print(List *L) { node *p = L->nil->next; while(p != L->nil) { cout<<p->key<<' '; p = p->next; } cout<<endl; } //搜尋,找出L中第一個關鍵字為k的結點,沒有則返回NULL node *List_Search(List *L, int k) { node *x = L->nil->next; while(x != L->nil && x->key!=k) x = x->next; return x; } //插入 void List_Insert(List *L, node *x) { //插入到表的前端 x->next = L->nil->next; L->nil->next->pre = x; L->nil->next = x; x->pre = L->nil; } //刪除 void List_Delete(List *L, node* x) { x->pre->next = x->next; x->next->pre = x->pre; delete x; }
三、練習
10.2-1 能,能 10.2-2 //結點 struct node { node *pre;//為了方便實現出棧操作 node *next; int key; node(int x):pre(NULL),next(NULL),key(x){} }; //鏈式棧 struct list { node *Head;//棧的起始結點 node *Top;//棧頂指標 list(){Head = new node(0);Top = Head;} }; //列印棧中的元素 void Print(list *L) { node *p = L->Head->next; while(p) { cout<<p->key<<' '; p = p->next; } cout<<endl; } //入棧 void Push(list *L, int x) { //構造一個新的結點 node *A = new node(x); //鏈入到棧頂位置,修改指標 L->Top->next = A; A->pre = L->Top; L->Top = A; } //出棧 int Pop(list *L) { if(L->Head == L->Top) { cout<<"error:underflow"<<endl; return -1; } //取出棧頂元素 int ret = L->Top->key; //修改指標 node *A = L->Top; L->Top = A->pre; L->Top->next = NULL; delete A; return ret; } 10.2-3 //結點 struct node { node *next; int key; node(int x):next(NULL),key(x){} }; //鏈式佇列 struct list { node *Head;//頭指標 node *Tail;//尾指標 list(){Head = new node(0);Tail = Head;} }; //列印 void Print(list *L) { node *p = L->Head->next; while(p) { cout<<p->key<<' '; p = p->next; } cout<<endl; } //入佇列 void Enqueue(list *L, int x) { //構造一個新的結點 node *A = new node(x); //鏈入尾部,修改指標 L->Tail->next = A; L->Tail = A; } //出佇列 int Dequeue(list *L) { if(L->Head == L->Tail) { cout<<"error:underflow"<<endl; return -1; } //取出隊頭結點,修改指標 node *A = L->Head->next; int ret = A->key; L->Head->next = A->next; if(A == L->Tail) L->Tail = L->Head; delete A; return ret; } 10.2-4 把哨兵的值置為一個不可能與x相等的值
10.2-5 10.2-6 使用帶尾指標的連結串列,令A的尾指標為tail,tail->next=B
10.2-7
//逆轉
void Reverse(list *L)
{
node *p = NULL, *q = L->Head, *r;
//依次修改指標,讓q是p->next,令q->next=p
while(1)
{
r = q->next;
q->next = p;
if(r == NULL)
{
L->Head = q;
break;
}
p = q;
q = r;
}
}
10.2-8