# 一、概念
(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-5 環形鏈表實現字典操作INSERT、DELETE、SEARCH](http://blog.csdn.net/mishifangxiangdefeng/article/details/7993190)
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
見[算法導論-10.2-8](http://blog.csdn.net/mishifangxiangdefeng/article/details/7706631)
- 前言
- 第6章 堆排序
- 6-3 Young氏矩陣
- 第7章 快速排序
- 第8章 線性時間排序
- 第9章 排序和順序統計學算法導論
- 算法導論 9.1-1 求第二小元素
- 第10章 10.1 棧和隊列
- 第10章 10.2 鏈表
- 第10章 10.3 指針和對象實現
- 第10章 10.4 有根樹的表示
- 第11章-散列表
- 第12章 二叉查找樹
- 第13章 紅黑樹
- 第14章 14.1 動態順序統計
- 算法導論-14-1-最大重疊點
- 算法導論-14-2-Josephus排列
- 第14章 14.3 區間樹
- 第15章 動態規劃
- 第16章 貪心算法
- 第18章 B樹
- 第19章-二項堆
- 第20章 斐波那契堆
- 第21章 用于不相交集合的數據結構
- 第22章 圖的基本算法 22.1 圖的表示
- 第22章 圖算法 22.2 廣度優先搜索
- 第22章 圖算法 22.3 深度優先搜索
- 第22章 圖的基本算法 22.4 拓撲排序
- 第22章 圖的基本算法 22.5 強聯通分支