数据结构(三):双向循环链表的函数实现
双向循环链表由于增加了一个前向指针,并且引入了循环,因此操作上有些复杂。头结点在双向循环链表依然保留。
一、 操作示意图
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;
}