链表
一、基本知识
- 链表中各对象按线性顺序排序;
- 链表与数组不同,数组按下表访问(随机),链表按指针访问(顺序)。
二、分类
1、单链表与双链表
- 单链表:next指针;
- 双链表:prev指针,next指针。
2、已排序与未排序
- 已排序链表:链表的线性顺序对应表中各元素的线性顺序;
- 未排序列表:元素按任意顺序出现。
3、环形与非环形
- 环形链表:表头元素的prev指向表尾元素,表尾的next指向表头元素;
- 非环形链表:表头元素无前驱,表尾元素无后继。
三、操作
链表的主要操作有搜索、插入和删除。
具体有两种实现链表的方式:
- head指针指向的元素地址存放数据,链表为空时,head=NULL(为分配任何空间);链表不为空时,含有一个元素的量表如下:

- head指向的地址不存放数据,链表为空时,分配了一个元素的空间。
(1) 无头指针
1、数据结构
链表中每个对象包含关键字和指针。
struct Node{ int data; Node* next; }; Node* head=NULL;
2、搜索操作
ListSearch采用简单的线性查找方法,找出线性表中第一个具有关键字k的元素,并返回指向该元素的指针。如果表中没有包含关键字为k的对象,则返回NULL。
Node* ListSearch( int k ) { Node* p = head; while (p != NULL && p->data != k) p = p->next; return p; }
3、插入操作
- 给定一个已设置了的新元素x,将x插入到链表的前段
void ListInsert(Node *x) { x->next = head; head = x; }
- 在链表尾部位置插入数据元素dataInsert
void Insert( int dataInsert ) { Node *pInsert = new Node; pInsert->data = dataInsert; if (head==NULL) { pInsert->next = head; head = pInsert; } else { Node *p = head; Node *q = head->next; while (q != NULL) { p = q; q = q->next; } p->next = pInsert; pInsert->next = q; } }
4、删除操作
- 删除链表中的一个元素x
void ListDelete(Node* x) { if (x==head) { head = x->next; } else { Node *p = head; while ( p->next != x) p = p->next; p->next = x->next; } }
- 删除链表中的数据元素datax
先调用ListSearch(datax)函数得到该元素的指针,而后调用ListDelete函数删除该元素。
(2)有头链表
设置哑对象(dummy object),将头节点设置为哑节点,要删除的节点肯定不会出现在链表头,简化边界条件的判定。
1、数据结构同上
2、创建链表
bool CreatNodeList() { head = new Node; if (head == NULL) { return false; } else { head->data = 0; head->next = NULL; return true; } }
3、搜索操作
Node *ListSearch2(int k) { if ( head == NULL ) { return head; } Node *p = head->next; while (p != NULL && p->data != k) p = p->next; return p; }
4、插入操作
bool ListInsert2(Node *x) { if ( head == NULL ) { return false; } x->next = head->next; head->next = x;
return true; }
5、删除操作
bool ListDelete2(Node* x) { if ( head == NULL ) { return false; } else { Node *p = head; while ( p->next != x) p = p->next; p->next = x->next; return true; } }
(3)双向链表无头指针
1、结构
struct Node { int data; Node *prev, *next; }; Node* head = NULL;
2、查找
与单链表相同
Node* ListSearch3(int k) { Node* p = head; while (p!=NULL && p->data!=k) p = p->next; return p; }
3、插入元素
void ListInsert3(Node* x) { x->next = head; x->prev = NULL; if (head != NULL) { head->prev = x; } head = x; }
4、删除元素
void ListDelete3(Node* x) { if (x->prev != NULL) { (x->prev)->next = x->next; } else { head = x->next; } if (x->next != NULL) { (x->next)->prev = x->prev; } }
(4)双链表带哑节点
假设有链表L和一个对象nil[L](表示链表L的哑节点),将链表算法中每次对NULL的应用,用对nil[L]的应用代替,将一般的双向链表变成一个带哨兵的环形双向链表。
- 哨兵元素nil[L]介于头节点和尾节点之间;
- nil[L]的next指针指向链表的头,prev指针指向表尾;
- 链表中第一个元素的prev指针指向nil[L],表尾的next指针指向nil[L]。
1、创建
bool CreatNodeList2() { head = new Node; if (head == NULL) { return false; } else { head->data = 0; head->next = head; head->prev = head; return true; } }
2、搜索
Node* ListSearch4(int k) { Node* p = head->next; while (p!=NULL && p->data!=k) p = p->next; return p; }
3、插入
void ListInsert4(Node* x) { x->next = head->next; (head->next)->prev = x; head->next = x; x->prev = head; }
4、删除
void ListDelete4(Node* x) { (x->prev)->next = x->next; (x->next)->prev = x->prev; }
浙公网安备 33010602011771号