#ifndef DULIST_H #define DULIST_H /* 线性表的双向链表存储结构 */ typedef void * elemtype; typedef struct dulnode { elemtype data;struct dulnode *prior,*next; }dulnode,*dulinklist; /*带头结点的双向循环链表的基本操作(14个) */ void list_init(dulinklist *l); void list_destory(dulinklist *l); void list_clear(dulinklist l); int list_empty(dulinklist l); int list_length(dulinklist l); int list_getelem(dulinklist l,int i,elemtype *e); int list_locateelem(dulinklist l,elemtype e,int(*compare)(elemtype,elemtype)); int list_priorelem(dulinklist l,elemtype cur_e,elemtype *pre_e); int list_nextelem(dulinklist l,elemtype cur_e,elemtype *next_e); dulinklist list_get_elemp(dulinklist l,int i); /* 另加 */ int list_insert(dulinklist l,int i,elemtype e); int list_delete(dulinklist l,int i,elemtype * e); void list_traverse(dulinklist l,void(*visit)(elemtype)); void list_traverse_back(dulinklist l,void(*visit)(elemtype));#endif
#include "includes.h" #define OVERFLOW -1 #define ERROR -2 #define OK 1 #define true 1 #define false 0void list_init(dulinklist *l) { /* 产生空的双向循环链表l */*l=(dulinklist)malloc(sizeof(dulnode));if(*l)(*l)->next=(*l)->prior=*l;elseexit(OVERFLOW); } void list_destory(dulinklist *l) {/* 操作结果:销毁双向循环链表l */dulinklist q,p=(*l)->next; /* p指向第一个结点 */while(p!=*l) /* p没到表头 */{q=p->next;free(p);p=q;}free(*l);*l=NULL; } void list_clear(dulinklist l) /* 不改变l */ { /* 初始条件:l已存在。操作结果:将l重置为空表 */dulinklist q,p=l->next; /* p指向第一个结点 */while(p!=l) /* p没到表头 */{q=p->next;free(p);p=q;}l->next=l->prior=l; /* 头结点的两个指针域均指向自身 */ } int list_empty(dulinklist l) { /* 初始条件:线性表l已存在。操作结果:若l为空表,则返回true,否则返回false */if(l->next==l&&l->prior==l)return true;elsereturn false; } int list_length(dulinklist l) { /* 初始条件:l已存在。操作结果:返回l中数据元素个数 */int i=0;dulinklist p=l->next; /* p指向第一个结点 */while(p!=l) /* p没到表头 */{i++;p=p->next;}return i; } int list_getelem(dulinklist l,int i,elemtype *e) { /* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */int j=1; /* j为计数器 */dulinklist p=l->next; /* p指向第一个结点 */while(p!=l&&(p=p->next)){j++;}if(p==l||j>i) /* 第i个元素不存在 */return ERROR;*e=p->data; /* 取第i个元素 */return OK; }int list_locate_elem(dulinklist l,elemtype e,int(*compare)(elemtype,elemtype)) { /* 初始条件:l已存在,compare()是数据元素判定函数 *//* 操作结果:返回l中第1个与e满足关系compare()的数据元素的位序。 *//* 若这样的数据元素不存在,则返回值为0 */int i=0;dulinklist p=l->next; /* p指向第1个元素 */while(p!=l){i++;if(compare(p->data,e)) /* 找到这样的数据元素 */return i;p=p->next;}return 0; }int list_priorelem(dulinklist l,elemtype cur_e,elemtype *pre_e) { /* 操作结果:若cur_e是l的数据元素,且不是第一个,则用pre_e返回它的前驱, *//* 否则操作失败,pre_e无定义 */dulinklist p=l->next->next; /* p指向第2个元素 */while(p!=l) /* p没到表头 */{if(p->data==cur_e){*pre_e=p->prior->data;return true;}p=p->next;}return false; }int list_next_elem(dulinklist l,elemtype cur_e,elemtype *next_e) { /* 操作结果:若cur_e是l的数据元素,且不是最后一个,则用next_e返回它的后继, *//* 否则操作失败,next_e无定义 */dulinklist p=l->next->next; /* p指向第2个元素 */while(p!=l) /* p没到表头 */ {if(p->prior->data==cur_e){*next_e=p->data;return true;}p=p->next;}return false; }dulinklist list_get_elemp(dulinklist l,int i) /* 另加 */ { /* 在双向链表l中返回第i个元素的地址。i为0,返回头结点的地址。若第i个元素不存在,*//* 返回NULL */int j;dulinklist p=l; /* p指向头结点 */if(i<0||i>list_length(l)) /* i值不合法 */return NULL;for(j=1;j<=i;j++)p=p->next;return p; } int list_insert(dulinklist l,int i,elemtype e) { /* 在带头结点的双链循环线性表l中第i个位置之前插入元素e,i的合法值为1≤i≤表长+1 *//* 改进算法2.18,否则无法在第表长+1个结点之前插入元素 */dulinklist p,s;if(i<1||i>list_length(l)+1) /* i值不合法 */return ERROR;p=list_get_elemp(l,i-1); /* 在l中确定第i个元素前驱的位置指针p */if(!p) /* p=NULL,即第i个元素的前驱不存在(设头结点为第1个元素的前驱) */return ERROR;s=(dulinklist)malloc(sizeof(dulnode));if(!s)return OVERFLOW;s->data=e;s->prior=p; /* 在第i-1个元素之后插入 */s->next=p->next;p->next->prior=s;p->next=s;return OK; }int list_delete(dulinklist l,int i,elemtype *e) { /* 删除带头结点的双链循环线性表l的第i个元素,i的合法值为1≤i≤表长 */dulinklist p;if(i<1) /* i值不合法 */return ERROR;p=list_get_elemp(l,i); /* 在l中确定第i个元素的位置指针p */if(!p) /* p=NULL,即第i个元素不存在 */return ERROR;*e=p->data;p->prior->next=p->next;//???没有考虑链表头?链表尾?p->next->prior=p->prior;free(p);return OK; } void list_traverse(dulinklist l,void(*visit)(elemtype)) { /* 由双链循环线性表l的头结点出发,正序对每个数据元素调用函数visit() */dulinklist p=l->next; /* p指向头结点 */while(p!=l){visit(p->data);p=p->next;}printf("\n"); }void list_traverse_back(dulinklist l,void(*visit)(elemtype)) { /* 由双链循环线性表l的头结点出发,逆序对每个数据元素调用函数visit()。另加 */dulinklist p=l->prior; /* p指向尾结点 */while(p!=l){visit(p->data);p=p->prior;}printf("\n"); }