双向循环链表


代码实现:

#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;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值