数据结构(三):双向循环链表的函数实现

双向循环链表由于增加了一个前向指针,并且引入了循环,因此操作上有些复杂。头结点在双向循环链表依然保留。

一、 操作示意图

1. 双向循环带头链表的空链表如图所示:

2. 双向循环带头链表一般情况如图所示:

 

3.  双向链表的插入操作:

    

          先连接上一节点,再连接下一节点;

          然后连接下一节点的前驱节点,最后修改前一节点的后驱节点。 

4. 双向链表的删除操作:

二、双向循环带头链表函数实现

#ifndef SUCCESS
#define SUCCESS 		1
#ifndef FAILED
#define FAILED 		0
#endif

#define TRUE 		1
#define FALSE 		0

typedef int Status;
typedef int dataType;

typedef struct node_{
	struct node_ *pre;
	dataType  data;
	struct node_ *next;
}LinkNodeDbCirc_st, *LinkNodeDbCirc_pt;  /*双向循环链表*/


/*       1.  链表的头结点创建*/

Status LinkListDbCirc_create_head(LinkNodeDbCirc_pt *head) 
{
	*head = (LinkNodeDbCirc_pt)malloc(sizeof(LinkNodeDbCirc_st)*sizeof(char));
	if(*head == NULL)
		return FAILED;

	*head->next = *head;
	*head->pre = *head;
	*head->data =  0;
	
	return SUCCESS;
}

/*       2.  链表是否为空*/

Status LinkListDbCirc_isEmpty(LinkNodeDbCirc_pt *head) 
{
	LinkNodeDbCirc_pt  pcur;
	if(head == NULL)
		return FAILED;

	pcur = *head;
	
	if(pcur->next == pcur && pcur->pre == pcur){
		return TRUE;
	}else if((head->next == head)^ (head->pre == head)){
		printf("when linklist is NULL, head->next must be equal head->pre\n");
		return FALSE ;
	}
	else	
		return FALSE;
}

/*       3.  链表的插入*/
Status LinkListDbCirc_insert(LinkNodeDbCirc_pt head,   dataType data)
{
	LinkNodeDbCirc_pt  pcur = head;
	LinkNodeDbCirc_pt  node = NULL;
	int i = 1;
	if(!head){
		printf(" The LinkList ' head node is NULL \n");
		return FAILED;
	}
	
	node = (LinkNodeDbCirc_pt)malloc(sizeof(LinkNodeDbCirc_st));
	if(!node){
		printf("LinkList_insert : malloc error\n");
		return FAILED;
	}

	
	 /*头插法*/
	node->pre = head;
	node->next = head->next;
	
	head->next->pre = node;
       head->next = node;
	
	memcpy(&node->data, &data, sizeof(dataType));

	return SUCCESS;
	
}
/*       3.  链表的插入*/
Status LinkListDbCirc_insertByLoc(LinkNodeDbCirc_pt head,  int location,  dataType data)
{
	LinkNodeDbCirc_pt  pcur = head;
	LinkNodeDbCirc_pt  node = NULL;
	int i = 1;
	if(!head){
		printf(" The LinkList ' head node is NULL \n");
		return FAILED;
	}

	if(location<=0) {
		printf("The location' value range is 1<= location <= LinkList_getLength(head) \n");
		return FAILED;
	}
	while(pcur->next !=head &&  (i<location)){
		pcur = pcur->next;
		i++;
	}

	if(pcur->next ==head || i>location)
		printf("Location is out of range\n");

	node = (LinkNodeDbCirc_pt)malloc(sizeof(LinkNodeDbCirc_st));
	if(!node){
		printf("LinkList_insert : malloc error\n");
		return FAILED;
	}

	node->pre = pcur;               /*先接上一节点,再连下一节点*/
	node->next = pcur->next;

	
	pcur->next->pre = node;    /*3 再处理后一节点的前节点,4最后处理前节点的后节点*/
	pcur->next = node;

	
	memcpy(&node->data, &data, sizeof(dataType));
	
	return SUCCESS;
	
}

/*       4. 链表的删除*/
Status  LinkListDbCirc_delByLoc(LinkNodeDbCirc_pt  head,  int location,  dataType * data)
{
	LinkNodeDbCirc_pt pcur = head;
	LinkNodeDbCirc_pt node,pnext;
	int i = 1;

	if(!pcur){
		printf("The LinkList ' head node is NULL\n");
		return FAILED;
	}
	if(location<=0){
		printf("The location' value range is 1<= location <= LinkList_getLength(head) \n");
		return FAILED;
	}

	while(pcur->next!=head && (i<location)){
		pcur = pcur->next;
		i++;
	}
	if(pcur->next == head || (i>location)){
		printf("location is out of range\n");
		return FAILED;
	}

	node = pcur->next;
	pnext = node->next;
	pcur->next = pnext;
	pnext->pre = pcur;

	node->next = NULL;
	node->pre = NULL;
	memcpy(data, &node->data, sizeof(dataType));
	free(node);
	return SUCCESS;
		
}

Status  LinkListDbCirc_delByData(LinkNodeDbCirc_pt  head,  dataType * data, int cnt)
{
	LinkNodeDbCirc_pt pcur = head;
	LinkNodeDbCirc_pt node = NULL;

	if(!pcur){
		printf("The LinkList ' head node is NULL\n");
		return FAILED;
	}
	cnt = 0;
	
	while(pcur->next != head){
		if(!memcmp(data, &pcur->next->data, sizeof(dataType))){
			node = pcur->next;
			node->next->pre = pcur;
			pcur->next = node->next;//1      跳过node节点
			
			cnt++;
			free(node);
			continue;
		}
		pcur = pcur->next;
	}
	
	if(!cnt){
		printf("This linkList doesn't have this node\n");
		return FAILED;
	}else{
		return SUCCESS;
	}
		
}

/*       4. 链表的查询*/
Status LinkListDbCirc_getElem(LinkNodeDbCirc_pt head,  int  location,  dataType data)
{
	LinkNodeDbCirc_pt pcur = head;
	LinkNodeDbCirc_pt node= NULL;
	int i = 1;

	if(!pcur){
		printf("This LinkNode ' head is NULL\n");
		return FAILED;
	}

	while(pcur->next!=head && i<location){
		pcur = pcur->next;
		i++;
	
	}

	if(pcur->next == head || i>location){
		printf("This  location is out of range\n");
		return FAILED;
	}

	if(i == location){
		node = pcur->next;
		memcpy(&data, &node->data, sizeof(dataType));
		return SUCCESS;
	}else{
		return FAILED;
	}

}

/*       5. 链表的修改*/
Status LinkListDbCirc_setElem(LinkNodeDbCirc_pt head,  int  location,  dataType data)
{
	LinkNodeDbCirc_pt pcur = head;
	LinkNodeDbCirc_pt node= NULL;
	int i = 1;

	if(!pcur){
		printf("This LinkNode ' head is NULL\n");
		return FAILED;
	}

	while(pcur->next !=head&& i<location){
		pcur = pcur->next;
		i++;
	
	}

	if(pcur->next==head || i>location){
		printf("This  location is out of range\n");
		return FAILED;
	}

	if(i == location){
		node = pcur->next;
		memcpy(&node->data, &data, sizeof(dataType));
		return SUCCESS;
	}else{
		return FAILED;
	}

}

/*       6. 双向循环链表的整表创建*/
/*
*    包含头结点
*    如果使用尾插法,需要维持尾指针,并且每次添加后向后移动尾指针
*    而使用头插法则不需要维持并移动除头指针外的其他变量
*
*/

Status LinkListDbCirc_create(LinkNodeDbCirc_pt *head,  int nodeNum)
{

	LinkNodeDbCirc_pt node;
	int i = 0;

	if(!head){
		printf("The head is NULL\n");
		return FAILED;
	}

	*head = (LinkNodeDbCirc_pt)malloc(sizeof(LinkNodeDbCirc_st));
	if(!*head){
		printf("LinkList_create : head node malloc error\n");
		return FAILED;
	}
	(*head)->next = *head;
	(*head)->pre = *head;
	(*head)->data = rand();
	
#ifdef TAILINSERT  //1 尾插法
	LinkNodeDbCirc_pt tail;
	tail = *head;
	
	while(i<nodeNum){
		node = (LinkNodeDbCirc_pt)malloc(sizeof(LinkNodeDbCirc_st));
		if(!node){
			printf("LinkList_create: node malloc error\n");
			return FAILED; 
		}
		node->data = rand();  /*可以修改*/

		node->pre = tail;
		node->next = tail->next;
		tail->next->pre = node;
		tail->next = node;
		
		tail = node;	 /*尾指针后移*/
	}
#else  //1 头插法

	while(i<nodeNum){
		node = (LinkNodeDbCirc_pt)malloc(sizeof(LinkNodeDbCirc_st));
		if(!node){
			printf("LinkList_create: node malloc error\n");
			return FAILED; 
		}
		node->data = rand();  /*可以修改*/

		node->pre = *head;
		node->next = (*head)->next;
		(*head)->next->pre = node;
		(*head)->next = node;	
	}
#endif
	return SUCCESS;
}

/*       7. 单链表的整表删除*/
/*
*  对于包含头结点的链表,空链表只有一个头结点和指向头结点的头指针
*  该函数删除有除最后一个节点外的所有节点,并将尾节点重新作为新的头节点
*/
Status LinkListDbCirc_delete(LinkNodeDbCirc_pt *head)  /*未保留头结点*/
{

	if(!head){
		printf("The head is NULL\n");
		return FAILED;
	}
#ifdef  DOUBLE_POINTER   //1 只需维持一个指针,充分利用二级指针
	LinkNodeDbCirc_pt node;
	while((*head)->next != *head){   /*当前节点和下一节点均不为空*/
		node = *head;

		node->pre->next = node->next;
		node->next->pre = node->pre;

		*head = node->next;     /*头指针后移*/
		free(node);
	}
	
	memset((*head)->data,0,sizeof((*head)->data));
	
#else   //1 维持两个指针
	LinkNodeDbCirc_pt p,q;
	int i=0;
	p = (*head)->next;
	
	while(p->next != *p){
		q = p->next;

		p->pre->next =p->next;
		p->next->pre = p->pre;
		
		free(p);
		
		p = q;
	}

#endif
	return SUCCESS;
}

 

 

 

 

 

 

 

 

posted @ 2019-05-18 15:50  叨陪鲤  阅读(82)  评论(0编辑  收藏  举报