循環鏈表是一個收尾相接的鏈表,將單鏈表的最後一個指針域改由NULL改成指向表頭結點這就是單鏈式的循環鏈表,並稱爲循環單鏈表node
帶頭結點的循環單鏈表的各類操做的算法實現與帶頭結點單鏈表的算法實現相似,差異僅在於算法判別當前結點p是否爲尾結點的條件不一樣。單鏈表中的判別條件爲p!=NULL或p->next!=NULL,而單循環鏈表判別條件是p!=L或p->next!=L算法
在循環單鏈表中附設尾指針有時候比附設頭指針更簡單。如:在用頭指針的循環單鏈表中找a1的時間複雜度是O(1),找an須要從頭找到尾,時間複雜度是O(n),若是用爲指針rear,找開始結點和終端結點的存儲位置分別是rear->next->next和rear。spa
void CreatCLLinkList(CLLinkList CL) { Node *rear,*s; rear=CL;//rear指針動態指向當前表尾,其初始值指向頭結點 int flag=1; int x; printf("Please input data and enter 0 end:\n"); while(flag) { scanf("%d",&x); if(x!=0) { s=(Node *)malloc(len); s->data=x; rear->next=s; rear=s; } else { flag=0; rear->next=CL;//最後一個節點的next域指向頭結點 } } }
#include<stdio.h> #include<stdlib.h> #define len sizeof(Node) typedef struct Node { int data; struct Node *next; }Node,*CLLinkList; void InitCLLinkList(CLLinkList *CL) { *CL=(CLLinkList)malloc(len); (*CL)->next=*CL; } void CreatCLLinkList(CLLinkList CL) { Node *rear,*s; rear=CL;//rear指針動態指向當前表尾,其初始值指向頭結點 int flag=1; int x; printf("Please input data and enter 0 end:\n"); while(flag) { scanf("%d",&x); if(x!=0) { s=(Node *)malloc(len); s->data=x; rear->next=s; rear=s; } else { flag=0; rear->next=CL;//最後一個節點的next域指向頭結點 } } } void PrintCLLinkList(CLLinkList CL) { Node *p; p=CL->next; printf("You input data is:\n"); for(;p!=CL;p=p->next) { printf("%-3d",p->data); } printf("\n"); } void InCLLinkList(CLLinkList CL,int i,int x) { Node *p,*s; int k=0; p=CL; if(i<=0) { printf("You enter location illegal:\n"); return; } while(p->next!=CL&&k<i-1) { k++; p=p->next; } if(p==CL) { printf("The insert position is not reasonable:\n"); return; } s=(Node *)malloc(len); s->data=x; s->next=p->next; p->next=s; printf("Insert successfully\n"); } void Print_CLLinkList(CLLinkList CL) { Node *p; p=CL->next; printf("Now you input data is:\n"); for(;p!=CL;p=p->next) printf("%-3d",p->data); } int main() { int i,x; CLLinkList CL; InitCLLinkList(&CL); CreatCLLinkList(CL); PrintCLLinkList(CL); printf("Please enter the location you want to insert:\n"); scanf("%d",&i); printf("Please enter the values you want to insert:\n") ; scanf("%d",&x); InCLLinkList(CL,i,x); Print_CLLinkList(CL); free(CL); return 0; }
#include<stdio.h> #include<stdlib.h> #define len sizeof(Node) typedef struct Node { int data; struct Node *next; }Node,*LinkList; void InitCLLinkList(LinkList *CL) { *CL=(LinkList)malloc(len); (*CL)->next=*CL; } void CreatCLLinkList(LinkList CL) { int flag=1,x; Node *rear,*s; rear=CL; printf("Please input data and enter 0 end:\n"); while(flag) { scanf("%d",&x); if(x!=0) { s=(Node *)malloc(len); s->data=x; rear->next=s; rear=s; } else { rear->next=CL; flag=0; } } } void DeleCLLinkList(LinkList CL,int i) { Node *p,*r; p=CL; int k=0; if(i<0) { printf("You enput i illegal!\n"); return; } while(p->next!=CL&&k<i-1) { p=p->next; k++; } if(p->next==CL) { printf("Delete Node i illegal!\n"); return; } r=p->next; p->next=r->next; free(r); } void PrintCLLinkList(LinkList CL) { Node *p; for(p=CL->next;p!=CL;p=p->next) { printf("%3d",p->data); } } int main() { LinkList CL; int i; InitCLLinkList(&CL); CreatCLLinkList(CL); printf("Please enter the i node you want to delete:\n"); scanf("%d",&i); DeleCLLinkList(CL,i); printf("The list after deleting is:\n"); PrintCLLinkList(CL); free(CL); return 0; }
方法一:先找到兩個鏈表LA,LB的表尾,分別用p,q指向它,而後將第一個鏈表的表尾與第二個鏈表的第一個結點連起來,修改第二個表的尾q,使它的鏈域指向第一個表頭3d
//頭指針合併循環鏈表 #include<stdio.h> #include<stdlib.h> #define len sizeof(Node) typedef struct Node { int data; struct Node *next; }Node,*CLLinkList; void InitCL_aLinkList(CLLinkList *CL_a) { *CL_a=(CLLinkList)malloc(len); (*CL_a)->next=*CL_a; } void InitCL_bLinkList(CLLinkList *CL_b) { *CL_b=(CLLinkList)malloc(len); (*CL_b)->next=*CL_b; } void CreatCL_aLinkList(CLLinkList CL_a) { Node *p,*s; int x,flag=1; p=CL_a; printf("Please input A data and enter 0 end:\n"); while(flag) { scanf("%d",&x); if(x!=0) { s=(Node *)malloc(len); s->data=x; p->next=s; p=s; } else { p->next=CL_a; flag=0; } } } void CreatCL_bLinkList(CLLinkList CL_b) { Node *p,*s; int x,flag=1; p=CL_b; printf("Please input B data and enter 0 end:\n"); while(flag) { scanf("%d",&x); if(x!=0) { s=(Node *)malloc(len); s->data=x; p->next=s; p=s; } else { p->next=CL_b; flag=0; } } } CLLinkList MergeCLLinkList(CLLinkList CL_a,CLLinkList CL_b) { Node *p,*q; p=CL_a; q=CL_b; while(p->next!=CL_a)//找到LA的表尾,用p指向它 p=p->next; while(q->next!=CL_b)//找到LB的表尾,用q指向它 q=q->next; q->next=CL_a;//修改LB的表尾指針,使之指向表LA的頭結點 p->next=CL_b->next; //修改LA的表尾指針,CL_b->next的意思是跳過CL_b頭結點 free(CL_b); return CL_a; } void PrintCLLinkList(CLLinkList CL) { printf("CL list is:\n"); for(Node *p=CL->next;p!=CL;p=p->next) printf("%-3d",p->data); printf("\n"); } int main() { CLLinkList CL_a,CL_b,CL; InitCL_aLinkList(&CL_a); InitCL_bLinkList(&CL_b); CreatCL_aLinkList(CL_a); CreatCL_aLinkList(CL_b); CL=MergeCLLinkList(CL_a,CL_b); PrintCLLinkList(CL_a); free(CL_a); return 0; }
方法二:若採用尾指針設置,無需遍歷找到尾結點,只需修改尾指針的指示域便可指針
CLLinkList MergeCLLinkList(CLLinkList RA,CLLinkList RB) { Node *p=RA->next;//保存RA的頭結點地址 RA->next=RB->next->next;//RB的頭結點練到RA的終端結點以後 RB->next=p;//將RA的頭結點鏈到RB的終端結點以後 free(RB->next);//釋放RB的頭結點 return RB;//返回新的鏈表的尾指針 }
#include<stdio.h> #define len sizeof(Node) #include<stdlib.h> typedef struct Node { int data; struct Node* next; }Node,*LinkList; void InitCLLinkList(LinkList *CL) { *CL=(LinkList)malloc(len); (*CL)->next=*CL; } //尾插法建立循環鏈表 void CreatCLLinkList(LinkList CL) { Node *s,*rear; int flag=1; rear=CL; printf("please input datas and input 0 over:\n"); int x; while(flag) { scanf("%d",&x); if(x!=0) { s=(Node *)malloc(len); s->data=x; rear->next=s; rear=s; } else { flag=0; rear->next=CL; } } } int LengthCLLinkList(LinkList CL) { int i=0; Node *p; p=CL->next; while(p!=CL) { i++; p=p->next; } return i; } int main() { LinkList CL; int length; InitCLLinkList(&CL); CreatCLLinkList(CL); length=LengthCLLinkList(CL); printf("The length of the circular list is:%d\n",length); free(CL) ; return 0; }