循環鏈表 是另外一種形式的鏈式存儲結構,特色是表中最後一個節點的指針域指向頭結點,整個鏈表造成一個環。因此從表中任意節點出發,均可以找到表中其餘的結點。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; } 複製代碼