目录
1 双链表
双链表:在单链表的每个结点中,再设置一个指向其前驱结点的指针域。双向链表中的结点有两个指针域,一个指向直接前驱,一个指向直接后继。
双链表的存储结构
typedef struct DNode{ //定义双链表结点类型
ElemType data; //数据域
struct DNode *prior, *next; //前驱和后继指针
}DNode,*DLinklist;
1.1 双链表的初始化(带头结点)
创建头结点,初始化两个指针。
//初始化双链表
bool InitDLinkList(DLinlist &L){
L=(DNode *) malloc(sizeof(DNode)); //分配一个头结点
if (L==NULL) //内存分配失败
return false;
L->prior = NULL; //头结点的prior永远指向NULL
L->next = NULL; //头结点之后暂时没有结点
return true;
}
1.2 双链表的插入
//在p结点之后插入s结点
bool InsertNextDNode(DNode *p,DNode *s){
if (p==NULL || s==NULL)
return false;
s->next = p->next;
if (p->next!=NULL) //如果p后面有后继结点的情况下
p->next->prior = s;
s->prior = p;
p->next = s;
return true;
}
1.3 双链表的删除
删除p结点的后继结点
//删除p结点的后继结点
bool DeleteNextDNode(DNode *p){
if (p==NULL)
return false;
DNode *q = p->next;
if (q == NULL) //判断p的后继结点是否存在
return false;
p->next = q->next;
if (q->next != NULL)
q->next->prior = p;
free(q);
return true;
}
循环释放各个数据结点
void DestoryList(DLinklist &L){
while (L->next !=NULL)
DeleteNextDNode(L);
free(L); //释放头结点
L = NULL; //头指针指向NULL
}
1.4 双链表的遍历
后向遍历
while(p!=NULL){
p = p->next;
}
前向遍历
while(p!=NULL){
p = p->prior;
}
前向遍历(跳过头结点)
while(p->prior!=NULL){
p = p->prior;
}
2 循环链表
2.1 循环单链表
单链表:从一个结点出发,只能找到其后续的各个结点。
循环单链表:从任何一个结点出发可以找到其它任何一个结点。
循环单链表的时间复杂度
从头结点找到尾部,时间复杂度为O(n),从尾部找到头部,时间复杂度为O(1)。
2.1.1 初始化一个循环链表
空表
type struct LNode{
ElemType data;
struct LNode *next;
}LNode,*Linklist;
//初始化一个循环链表
bool InitList(Linklist &L){
L = (LNode*)malloc(sizeof(LNode));
if (L==NULL)
return false;
L->next = L;
return true;
}
2.1.2 判断循环链表是否位空
//判断循环单链表是否为空
bool Empty(Linklist &L){
if(L->next == L)
return true;
else
return false;
}
2.1.3 判断结点p是否为表尾结点
//判断循环单链表是否为空
bool isTail(Linklist &L, LNode *p){
if(p->next == L)
return true;
else
return false;
}
2.2 循环双链表
2.2.1 循环双链表的初始化
typedef struct DNode{ //定义双链表结点类型
ElemType data; //数据域
struct DNode *prior, *next; //前驱和后继指针
}DNode,*DLinklist;
boolInitDLinkList(DLinklist &L){
L = (DNode *)malloc(sizeof(DNode));
if (L==NULL)
return false;
L->prior = L;
L->next = L;
return true;
}
2.2.2 循环双链表的插入
和双链表不同的是,循环双链表的后继指针没有指向NULL的,可以不用判断结点是否为NULL。
//在p结点之后插入s结点
bool InsertNextDNode(DNode *p,DNode *s){
s->next = p->next;
p->next->prior = s;
s->prior = p;
p->next = s;
}
2.2.3 循环双链表的删除
//删除p结点的后继结点q
bool DeleteNextDNode(DNode *p){
p->next = q->next;
q->next->prior = p;
free(q);
}