1.循环单链表
1.循环单链表特点:
链表中最后一个结点的指针域不再是结束标志,而是指向整个链表的第一个结点,从而使链表形成一个环。和单链表相同,循环单链表也有带头结点和不带头结点两种。带头结点的循环单链表实现插入和删除操作较为方便,且更加适用。
2. 单链表与循环单链表比较:
循环单链表可以从尾到头,而单链表不能从尾到头。因此处理的数据序列具有环形结构特点时,适合采用循环单链表。
3. 带头结点的循环单链表和带头结点的单链表比较:
①在初始化函数中,把语句( * head)->next=NULL改为( * head)->next=* head,即形成一个环
②在其他函数中,循环判断条件p->next!=NULL和p->next->next!=NULL中的NULL改成头指针head。
2.双向链表
双向链表特点:
每个节点除了有后继指针域还有一个前驱指针域。双向链表的分类:
双向链表有:带头结点和不带头结点的双向链表(但是带头结点的双向链表更为常用)。也有循环和非循环之分,循环结构的双向链表更为常用。因此下面讨论的是带头结点的循环双链表。双向循环链表结点的结构体定义
typedef struct Node { DataType data; struct Node *next; struct Node *prior; }DLNode;
data域、next域、prior域。其中data域是数据域,next域为指向后继结点的指针域,prior域为指向前驱结点的指针域。
双向链表的优点:
在单链中查找当前结点的后继结点并不困难,可以通过当前结点的next指针进行,但要查找当前结点的前驱结点,就要从头指针head开始重新进行。对于一个要频繁进行当前结点的后继结点和前驱结点的应用来说,使用双向链表很有效。
3.双向循环链表的实现
在双向链表中,有如下指针关系:设指针p指向双向循环链表中的第i个位置,则p->next指向i+1个结点。p->next->prior仍指向第i个结点,即p->next->prior==p;同样p->prior指向第i-1个结点,p->prior->next仍指向第i个结点,即p->prior->next==p;双向循环链表关系算法可以方便算法设计。
初始化
void ListInitiate(DLNode **head) { *head=(DLNode *)malloc(sizeof(SLNode)); (*head)->prior=*head; //构成前驱指针循环链表 (*head)->next=*head; //构成后继指针循环链表 }
插入数据元素
int ListInsert(DLNode *head,int i,DataType x)//在带头结点的双向循环链表head的第i个结点前,插入一个存放 //数据元素x的结点,插入成功返回1,失败返回0 { DLNode *p,*q int j; p=head->next; j=0; while(p!=head&&j<i) { p=p->next; j++; } if(j!=i) { printf("参数i错误!"); return 0; } s=(DLNode*)malloc(sizeof(SLNode)); s->data=x; s->prior=p->prior; //新结点指向前一个结点(中——>前) p->prior->next=s; //新结点结点指向前一个结点(前->中) s->next=p; //新节点指向后结点 (中->后) p->prior=s; //后结点指向新节点 (后->中) return 1; }
和单链表相比,双向循环链表的插入算法指针p可以直接指在第i个结点上,而不需要让指针p指在i-1上
删除数据元素
int ListInitiate(DLNode *head,int i,DataType *x) { DlNode *p; int j; p=head->next; j=0 } if(j!=i) { printf("删除数据元素为值参数出错!"); return 0; } *x=p->data; p->prior->next=p->next; p->next-prior=p->prior; free(p); return 1;
求当前数据元素个数ListLength(DLNode *head)
int ListLength(SLNode *head) { DLNode *p=head; int size=0; while(p->next!=NULL) { p=p->next; size++; } return szie; }
撤销内存空间Destroy(DLNode **head)
void Destory(DLNode **head) { DLNode *p,*q; int i,n=ListLength(*head); p=*head; for(i=0;i<=n;i++) { q=p; p=p->next; free(p); } *head=NULL; }