一、双向链表


1)双向链表结构定义
#define ERROR 0;
#define OK 1;
typedef int ret; //函数返回类型
typedef int Element;
//定义结点
typedef struct Node {
Element data;
Node *prior;
Node *next;
}Node;
typedef Node *LinkList;
2)创建双向链表

ret createLise(LinkList *l) {
//创建指向头结点的链表
*l = (LinkList)malloc(sizeof(Node));
if(*l == NULL) return ERROR;
(*l)->next = NULL;
(*l)->prior = NULL;
(*l)->data = -1;
//新增数据
LinkList p = *l;
for(int i = 1, i <= 10; i++) {
//创建一个新结点
LinkList newNode = (LinkList)malloc(sizeof(Node));
if(newNode == NULL) return ERROR;
newNode->data = i;
newNode->next = NULL;
//newNode的前驱是p;
newNode->prior = p;
//p的后继是newNpde
p->next = newNpde;
//更新p 的值,p指向p的后继
p = p->next;
}
return YES;
}
3)打印循环链表的元素
void displayList(LinkList l) {
//因为第一个结点为头结点
linkList p = l->next;
if(p == NULL) return NULL;
while(p) {
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
4)双向链表插入元素

int listInsert(LinkList *l, int place, Element e) {
LinkList p, newNode;
int i;
if (place < 1) return ERROR;
//创建新结点
newNode = (LinkList)malloc(sizeof(Node));
if (newNode == NULL) return ERROR;
newNode->data = e;
newNode->next = NULL;
newNode->prior = NULL;
//p 赋值为头结点
p = *l;
//找到 place - 1 位置的结点
for(i = 1; i < place && p; i++) {
p = p->next;
}
//说插入的位置越界
if(p == NULL) return ERROR;
//如果为最后一个元素
if (p->next == NULL) {
newNode->prior = p;
p->next = newNode;
} else {
//p->next 的前驱赋值 newNode;
p->next->prior = newNode;
//newNode 的 next 赋值为p原来的next;
newNode->next = p->next;
//新结点的前驱赋值为p
newNode->prior = p;
//p->next赋值为新结点
p->next = newNode;
}
return YES;
}
5)删除双向链表指定位置上的结点

ret listDelete(LinkList *l, int place) {
LinkList p;
p = *l;
if(*l == NULL)
printf("链表以为空!");
if(place > 1);
printf("删除位置不合法!");
//找到 place - 1 位置的结点
for (int i = 1; i < place; i++) {
p = p->next;
}
如果第place 位置的结点不存在,或者要删除的位置不合法返回ERROR
if(p == NULL || i>place) {
return ERROR;
}
//指向要
LinkList delNode = p->next;
p->next = delNode->next;
if (delNode->next != NULL) {
delNode->next->prior = p;
}
free(delNode);
return YES;
}
6)删除双向链表指定值的结点
删除思想跟第五差不多,但是实现方法有差异
ret delList(LinkList *l, Element e) {
LinkList p;
p = (*l)->next;
if (p == NULL) {
printf("链表以为空!");
}
while (p) {
//判断当前结点是否是要删除的结点
if (p->data == e) {
//将要删除的结点前驱结点的next赋值为要删除结点的后继结点
p->prior->next = p->next;
//判断要删除结点的后继结点是否存在
if( p->next != NULL)
//将要删除结点的后继结点的前驱赋值为要删除结点的前驱结点
p->next->prior = p->prior;
//释放要删除的结点
free(p);
break;
}
p = p->next;
}
return YES;
}
7)在双向链表中查找元素
int findElement(LinkList l, Element e) {
int i = 1;
linkList temp;
temp = l->next;
while(temp) {
if (temp == e) {
break;
}
temp = temp->next;
i++;
}
return i;
}
8)在双向链表中更新结点
ret = replaceLinkList(LinkList *l, int index, Element e) {
LinkList temp = (*l)->next;
for (int i = 1; i<index; i++) {
temp = temp->next;
}
temp->data = e;
return YES;
}
2、双向循环链表

1)双向链表结构定义
#define ERROR 0;
#define OK 1;
typedef int ret; //函数返回类型
typedef int Element;
//定义结点
typedef struct Node {
Element data;
Node *prior;
Node *next;
}Node;
typedef Node *LinkList;
2)双向循环链表初始化
ret createList(LinkList *l) {
//创建一个头结点
*l = (LinkList)malloc(sizeof(Node));
if(*l == NULL) return ERROR;
(*l)->data = -1;
(*l)->next = NULL;
(*l)->prior = NULL;
LinkList p = *l;
//增加结点
for(int i = 1; i < 10; i++) {
LinkList newNode = (LinkList)malloc(sizeof(Node));
if(newNode == NULL) continue;
p->next = newNode;
newNode->data = i;
newNode->next = *l;
newNode->prior = p;
p = p->next;
}
return YES;
}
3)双向循环链表插入元素

/*当插入位置超过链表长度则插入到链表末尾*/
ret listInsert(LinkList *l, int place, Element e) {
LinkList p, newNode;
int i = 1;
//双向链表为空
if (*l == NULL) return ERROR;
//插入位置非法
if (place < i) return ERROR;
//找到 place - 1 位置的结点
for(p = *l; i< place, p->next != *l; p = p->next, i++;)
//创建新结点
newNode = (LinkList)malloc(sizeof(Node));
//创建失败
if(newNode == NULL) return ERROR;
newNode->data = e;
//新结点的next 指向 p->next
newNode->next = p->next;
//新结点的前驱指向 p
newNode->prior = p;
//p 的后继指向新结点
p->next = newNode;
//判断newNode是否为最后一个结点
if(*l != newNode->next) {
//新结点后继结点的前驱赋值为 新结点
newNode->next->prior = newNode;
} else {
//将首结点的前驱赋值为新结点
(*l)->prior = newNode;
}
}
4)遍历双向循环链表
void displayList(LinkList l) {
if (l == NULL) {
printf("链表为空!");
return;
}
printf("双向循环链表内容: ");
LinkList p = p->next;
while(p != l) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
5)双向循环链表删除结点

ret delList(LinkList *l, int index, Element *e) {
LinkList p;
p = (*l)->next;
if((*l)->next == l) {
printf("链表为空!");
return ERROR;
}
//如果删除到只剩首元结点,直接将链表置空
if(p->next == *l) {
free(*l)
(*l) = NULL;
return YES;
}
int i = 1;
if(index < i) {
printf("删除位置不合法!");
}
while(i < index) {
p = p->next;
}
*e = p;
//要删除结点的后继的前驱赋值为要删除结点的前驱
p->next->prior = p->prior;
//要删除的结点的前驱的后继赋值为要删除结点的后继
p->prior->next = p->next;
free(p);
return YES;
}