#include<stdio.h>
#include<stdlib.h>
// 双向循环链表
typedef int datatype_t;
typedef struct node{
datatype_t data;
struct node *prior;
struct node *next;
} dlinklist_t;
// 创建空的双向循环链表
dlinklist_t * dlinklist_create() {
dlinklist_t *dl;
dl = (dlinklist_t *)malloc(sizeof(dlinklist_t));// malloc是从堆里面获得的空间
dl->next = dl->prior = dl;
return dl;
}
// 使用头插法向链表中插入数据
void dlinklist_head_insert(dlinklist_t *dl, datatype_t value) {
dlinklist_t *temp = (dlinklist_t *)malloc(sizeof(dlinklist_t));
temp->data = value;
// 这样写可以同时兼容头结点有数据和没有数据的情况
dlinklist_t *pnext = dl->next;
dl->next = temp;
temp->next = pnext;
pnext->prior = temp;
return;
}
// 实现尾插法 双向循环链表的尾插是非常快的 因为可以直接得到需要的位置 时间复杂度为O(1)
void dlinklist_tail_insert(dlinklist_t *dl, datatype_t value) {
dlinklist_t *temp = (dlinklist_t *)malloc(sizeof(dlinklist_t));
temp->data = value;
temp->next = dl;
temp->prior = dl->prior;
dl->prior->next = temp;
dl->prior = temp;
return;
}
// 显示
void dlinklist_show(dlinklist_t *dl) {
dlinklist_t *temp = dl;
while (dl->next != temp)
{
dl = dl->next;
printf("%d ", dl->data);
}
printf("\n");
return;
}
// 判断链表是否为空
int dlinklist_empty(dlinklist_t *dl) {
return dl->next == dl ? 1 : 0;
}
// 删除数据节点
int dlinklist_head_delete(dlinklist_t *dl) {
// 删除前先判断是否为空
if (dlinklist_empty(dl))
{
printf("empty");
return 0;
}
// 保存被删除节点的地址
dlinklist_t *temp = dl->next;
// 保存被删除节点的下一个节点的地址
dlinklist_t *nnext = temp->next;
// 将节点从双向循环链表中删除
dl->next = nnext;
nnext->prior = dl;
// 保存数据并返回
datatype_t value = temp->data;
// 释放被删除节点占用的内存空间
free(temp);
temp = NULL;
return value;
}
int main() {
dlinklist_t *dl;
dl = dlinklist_create();
dlinklist_head_insert(dl, 100);
dlinklist_head_insert(dl, 200);
dlinklist_head_insert(dl, 300);
dlinklist_show(dl);
dlinklist_tail_insert(dl, 400);
dlinklist_show(dl);
printf("\n从节点中删除了:%d\n", dlinklist_head_delete(dl));
dlinklist_show(dl);
printf("\n从节点中删除了:%d\n", dlinklist_head_delete(dl));
dlinklist_show(dl);
printf("\n从节点中删除了:%d\n", dlinklist_head_delete(dl));
dlinklist_show(dl);
dlinklist_tail_insert(dl, 500);
dlinklist_tail_insert(dl, 600);
dlinklist_show(dl);
printf("\n从节点中删除了:%d\n", dlinklist_head_delete(dl));
dlinklist_show(dl);
return 0;
}
下面是执行效果
另一段参考代码
#include "stdio.h"
#include "stdlib.h"
typedef int datatype_t;
typedef struct node {
datatype_t data;
struct node *prior;
struct node *next;
} dlinklist_t;
//创建空的双向循环链表
dlinklist_t *dlinklist_create() {
dlinklist_t *head = (dlinklist_t *) malloc(sizeof(dlinklist_t));
if (head == NULL) {
exit(0);
}
head->next = head;
head->prior = head;
return head;
}
//双向循环链表插入数据节点
void dlinklist_insert(dlinklist_t *head, datatype_t value) {
dlinklist_t *temp = (dlinklist_t *) malloc(sizeof(dlinklist_t));
if (temp == NULL) {
exit(0);
}
temp->data = value;
//获取第一个有数据的节点的地址 为 head->next
//如果此时只有一个头结点 则假设存在有数据的节点
dlinklist_t *pnext = head->next;
//使头结点与新插入的节点建立关系
head->next = temp;
temp->prior = head;
//使头结点的下一个节点与新插入的节点建立关系
temp->next = pnext;
pnext->prior = temp;
return;
}
//判断双向循环链表是否为空
int dlinklist_empty(dlinklist_t *head) {
return head->next == head ? 1 : 0;
}
//删除数据节点 头删法
datatype_t dlinklist_delete(dlinklist_t *head) {
if (dlinklist_empty(head)) {
printf("empty\n");
return -1;
}
//保存被删除的节点的地址
dlinklist_t *temp = head->next;
//保存被删除数据节点的下一个节点的地址
dlinklist_t *nnext = temp->next;
//将节点从双向循环链表中移出
head->next = nnext;
nnext->prior = head;
//保存数据并返回
datatype_t data = temp->data;
free(temp);
temp = NULL;
return data;
}
//显示节点数据
void dlinklist_show(dlinklist_t *head) {
dlinklist_t *p = head;
while (head->next != p) {
head = head->next;
printf("%d ", head->data);
// printf("%d ", head->next->data);
// head = head->next;
}
printf("\n");
return;
}
int main() {
dlinklist_t *head = dlinklist_create();
dlinklist_insert(head, 3);
dlinklist_insert(head, 4);
dlinklist_insert(head, 44);
dlinklist_insert(head, 5);
dlinklist_insert(head, 55);
dlinklist_show(head);
dlinklist_delete(head);
dlinklist_show(head);
return 0;
}
运行效果