代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
双向循环链表:首先要假设某个节点为头结点
说明:
pb一般表示当前节点
pf一般表示当前节点的前项节点
*/
#include <stdio.h>
#include <malloc.h>
typedef struct DbNode
{
int data;
struct DbNode *pre;
struct DbNode *next;
}DbNode;
/****************************创建新节点********************************/
/************创建新节点时,让其前驱和后继指针都指向本身**************/
DbNode *CreateNode(int data)
{
DbNode *pnode = (DbNode *)malloc(sizeof(DbNode));
pnode->data = data;
pnode->pre = pnode;
pnode->next = pnode;
return pnode;
}
/******************在表尾插入新节点,返回表头节点*************************************
*************************************************************************************/
DbNode *AppendNode(DbNode *head , int data)
{
//node为插入的节点
DbNode *node = CreateNode(data);
DbNode *pb = NULL;
DbNode *pf = NULL;
if(head == NULL)
{
return NULL;
}
//退出时,pf就为尾结点了
pf = pb = head->next; //从第二个节点开始的
while(pb != head)
{
pf = pb;
pb = pb->next;
}
//尾结点的next指向新节点,新节点的next指向首节点,首节点的pre指向新节点,新节点的pre指向尾结点
pf->next = node;
node->pre = pf;
node->next = head;
head->pre = node;
return head;
}
/**********************插入一个结点到大于data的结点之前,返回表头********************
分为在表头插入和不再表头插入:
思路是,A的next指向B,B的pre指向A;B的next指向C,C的pre指向B
*************************************************************************************/
DbNode *InsertNode(DbNode *head , int data)
{
DbNode *pb = NULL , *pf = NULL;
DbNode *node = NULL;
/*新建数据节点:空链表,新建节点作为头结点*/
node = CreateNode(data);
if(head == NULL)
{
head = node;
return node;
}
/*data小于表头数据,【插入到表头之前】*/
if(data<head->data)
{
head->pre->next = node; /*把新建节点作为表头,即尾节点的next指向node*/
node->pre = head->pre; /*node的pre指向尾节点*/
node->next = head; /*node的next指向head*/
head->pre = node; /*head的pre指向node*/
return node;
}
/*退出时,pf指向最后个结点*/
pf = pb = head->next;
while(pb->data<=data&& pb != head)//从第二个节点开始的
{
pf = pb;
pb = pb->next;
}
pf->next = node;//让【前项节点】的【后项】指针指向【插入的结点】
node->pre = pf; //【插入的结点】的【前项】指针指向【前项节点】
node->next = pb;//【插入的结点】的【后项】指针指向【后项节点】
pb->pre = node; //【后项节点】的【前项】指针指向【插入的结点】
return head;
}
/************************************************************************************
打印整个链表
************************************************************************************/
void PrintList(DbNode *head)
{
DbNode *pnode = NULL;
if(head == NULL) /*head为NULL表示链表空*/
{
return;
}
pnode = head;
while(pnode->next != head) /*退出时,pnode为最后个结点了*/
{
printf("%d " , pnode->data);
pnode = pnode->next;
}
printf("%d " , pnode->data); /*打印最后个节点的数据*/
printf("\n");
}
/************************************************************************************
删除双向循环链表中第一次遇见的data=num的节点
************************************************************************************/
DbNode *delete(DbNode * head,int num)
{
DbNode *pf,*pb = head;
if(head==NULL)
{
printf("\nempty list!\n");
goto end;
}
//退出时[1]当前结点的data=num了 [2]最后个节点的data=num了或者当前循环链表中不存在data=num的
while (pb->data!=num && pb->next!=head)
{
pf=pb;
pb=pb->next;
}
//[1]当前结点的data=num了;即链表中存在结点的data=num
if(pb->data==num)
{
if(pb==head)
{
if (pb->next == head && pb->pre == head) //如果只有一个节点
{
free(pb);
head = NULL;
goto end;
}
pb->next->pre = head->pre; //第二个结点的pre指向最后个结点
head->pre->next = pb->next; //最后个结点的next指向第二个结点
head=pb->next; //第二个结点作为head
}
else
{
pf->next = pb->next;
pb->next->pre = pf;
}
free(pb);
printf("The node is deleted\n");
}
//[2]链表中不存在结点的data=num
else
printf("The node not been found!\n");
end:
return head;
}
int main()
{
/*创建表头节点,数据为2*/
DbNode *head = CreateNode(2);
printf("---------------------acreat-----------------------\n");
PrintList(head);
//往链表尾追加结点
printf("---------------------append-----------------------\n");
head=AppendNode(head,3);
head=AppendNode(head,8);
head=AppendNode(head,4);
head=AppendNode(head,6);
PrintList(head);
//往第一个大于此数的前面插入结点
printf("---------------------insert-----------------------\n");
head = InsertNode(head , 1);
head = InsertNode(head , 10);
head = InsertNode(head , 5);
PrintList(head);
printf("---------------------delete-----------------------\n");
head = delete(head,1);
head = delete(head,10);
head = delete(head,8);
PrintList(head);
return 0;
}