数据结构(6)线性表之双循环链表
前言
同单链表一样,双向链表也可以是循环表。链表最后一个结点的next指针指向头结点,头结点的Prior指针指向最后一个结点,形成循环。
带头结点的空链表
带头结点的非空链表
添加管理结构
双循环链表的插入与删除
实际上,在循环链表中,无论是头部插入还是尾部插入,都可以理解为按位置插入(就是在两个结点中间进行插入):头部插入是在头结点和首元结点之间进行插入,尾部插入则是在最后一个结点和头结点之间进行插入。这样,我们只需要知道如何在两个结点中间进行插入,就可以实现双循环链表诸多的插入操作。而如何在两个结点中间进行插入,跟在双链表中是一致的,也就是需要考虑四个指针的指向
-
待插入结点的Prior指针
-
待插入结点的Next指针
-
待插入结点前驱的Next指针
-
待插入结点后继的Prior指针
这样,本来区分开的头部插入、尾部插入操作可以整合为按位置插入,参数传要插入的位置即可。但是考虑到我们的双链表增加了管理结构,还需要保证管理结构指针的正确性,所以在代码中仍是区分实现的。
尾部插入也是两个结点中的插入
实际上
插入与删除类似
其他操作同双链表一致,只是判断循环结束的条件有区别罢了,不细说
全部代码
DCList.h
#ifndef DCList_h
#define DCList_h
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define ElemType int
typedef struct Node{
ElemType data;
struct Node *prior;
struct Node *next;
}Node,*PNode;
typedef struct List{
PNode first;
PNode last;
int size;
}List;
//初始化
void InitDCList(List *list);
//1.尾部插入
void push_back(List *list,ElemType x);
//2.头部插入
void push_fount(List *list,ElemType x);
//3.展示
void show_list(List *list);
//4.尾部删除
void pop_back(List *list);
//5.头部删除
void pop_fount(List *list);
//6.按值插入(要求插入前的链表是有序的(此处为顺序
void insert_val(List *list,ElemType x);
//7.按值查找
Node* find(List *list,ElemType x);
//8.获取长度
int length(List *list);
//9.按值删除
void delete_val(List *list,ElemType x);
//10.排序
void sort(List *list);
//11.逆置(前后转换
void resver(List *list);
//12.清除单链表 ->只清除数据,保留头结点
void clearList(List *list);
//13.摧毁 ->包括头结点在内一起摧毁
void destroy(List *list);
//生成一个结点
Node* getNode(ElemType x);
#endif /* DCList_h */
DCList.cpp
#include "DCList.h"
//初始化
void InitDCList(List *list){
//申请头结点
Node *s = (Node *)malloc(sizeof(Node));
assert(s != NULL);
list->first = list->last = s;
//使链表循环
list->first->prior = list->last;
list->last->next = list->first;
list->size = 0;
}
//1.尾部插入
void push_back(List *list,ElemType x){
Node *s = getNode(x);
//s的前驱指向最后一个结点
s->prior = list->last;
//s的后继指向头结点
s->next = list->last->next;
//头结点的前驱指向s
//list->last->next->prior = s;
s->next->prior = s;
//最后一个结点的后继指向s
list->last->next = s;
//重新设置last指针的值
list->last = s;
list->size ++</