循环链表 是另外一种形式的链式存储结构,特色是表中最后一个节点的指针域指向头结点,整个链表造成一个环。因此从表中任意节点出发,均可以找到表中其余的结点。bash
单向循环链表 的操做和单链表基本一致,惟一不一样的是,当链表遍历时,判断当前指针p
是否指向尾结点的终止条件不一样:markdown
p!=NULL
或 p->next !=NULL
p!=L
或 p->next != L
typedef int Status;// Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int ElemType;// ElemType类型根据实际状况而定,这里假设为int
typedef struct Node{
ElemType data;
struct Node *next;
}Node;
typedef struct Node * LinkList;
复制代码
须要考虑两种状况:函数
Status CreateList(LinkList *L){ int item; LinkList temp = NULL; LinkList target = NULL; printf("输入节点的值,输入0结束\n"); while(1) { scanf("%d",&item); if(item==0) break; //若是输入的链表是空。则建立一个新的节点,使其next指针指向本身 (*head)->next=*head; if(*L==NULL) { *L = (LinkList)malloc(sizeof(Node)); if(!L)exit(0); (*L)->data=item; (*L)->next=*L; } else { //输入的链表不是空的,寻找链表的尾节点,使尾节点的next=新节点。新节点的next指向头节点 for (target = *L; target->next != *L; target = target->next); temp=(LinkList)malloc(sizeof(Node)); if(!temp) return ERROR; temp->data=item; temp->next=*L; //新节点指向头节点 target->next=temp;//尾节点指向新节点 } } return OK; } 复制代码
next
指针指向新结点next
指针指向首元结点next
指向前一结点的next
next
指针指向新结点Status ListInsert(LinkList *L, int place, int num){ LinkList temp ,target; int i; if (place == 1) { //若是插入的位置为1,则属于插入首元结点,因此须要特殊处理 //1. 建立新结点temp,并判断是否建立成功,成功则赋值,不然返回ERROR; //2. 找到链表最后的结点_尾结点, //3. 让新结点的next 执行头结点. //4. 尾结点的next 指向新的头结点; //5. 让头指针指向temp(临时的新结点) temp = (LinkList)malloc(sizeof(Node)); if (temp == NULL) { return ERROR; } temp->data = num; for (target = *L; target->next != *L; target = target->next); temp->next = *L; target->next = temp; *L = temp; }else{ //若是插入的位置在其余位置; //1. 建立新结点temp,并判断是否建立成功,成功则赋值,不然返回ERROR; //2. 先找到插入的位置,若是超过链表长度,则自动插入队尾; //3. 经过target找到要插入位置的前一个结点, 让target->next = temp; //4. 插入结点的前驱指向新结点,新结点的next 指向target原来的next位置 ; temp = (LinkList)malloc(sizeof(Node)); if (temp == NULL) { return ERROR; } temp->data = num; for ( i = 1,target = *L; target->next != *L && i != place - 1; target = target->next,i++) ; temp->next = target->next; target->next = temp; } return OK; } 复制代码
next
指针指向的下一结点next
指针指向首元结点target
next
指针指向,要删除结点的next
指向的结点Status LinkListDelete(LinkList *L,int place){ LinkList temp,target; int i; //temp 指向链表首元结点 temp = *L; if(temp == NULL) return ERROR; if (place == 1) { //①.若是删除到只剩下首元结点了,则直接将*L置空; if((*L)->next == (*L)){ (*L) = NULL; return OK; } //②.链表还有不少数据,可是删除的是首结点; //1. 找到尾结点, 使得尾结点next 指向头结点的下一个结点 target->next = (*L)->next; //2. 新结点作为头结点,则释放原来的头结点 for (target = *L; target->next != *L; target = target->next); temp = *L; *L = (*L)->next; target->next = *L; free(temp); }else{ //若是删除其余结点--其余结点 //1. 找到删除结点前一个结点target //2. 使得target->next 指向下一个结点 //3. 释放须要删除的结点temp for(i=1,target = *L;target->next != *L && i != place -1;target = target->next,i++) ; temp = target->next; target->next = temp->next; free(temp); } return OK; } 复制代码
int findValue(LinkList L,int value){ int i = 1; LinkList p; p = L; //寻找链表中的结点 data == value while (p->data != value && p->next != L) { i++; p = p->next; } //当尾结点指向头结点就会直接跳出循环,因此要额外增长一次判断尾结点的data == value; if (p->next == L && p->data != value) { return -1; } return i; } 复制代码