基礎---迴圈連結串列的實現
阿新 • • 發佈:2021-08-25
3.迴圈連結串列的實現
3.1定義一個結點
typedef struct list{
int data;
struct list *next;
}list;
//data為儲存的資料,next指標為指向下一個結點
//和單鏈表的結點一樣。
3.2初始化一個結點
//初始結點 list *initlist(){ list *head=(list*)malloc(sizeof(list)); if(head==NULL){ printf("建立失敗,退出程式"); exit(0); }else{ head->next=NULL; return head; } }
//由於迴圈連結串列的特殊性,已經為之後的方便使用,一個初始化好的迴圈連結串列的頭結點的next需要指向自身。
//所以上面的操作是不完整的,在具體使用的時候,我們還需要在主函式里加上如下操作:
在主函式重呼叫可以是這樣
//////////初始化頭結點//////////////
list *head=initlist();
head->next=head;
3.3建立迴圈連結串列
注意是’建立---插入資料‘,這說明一個迴圈連結串列的建立是在資料逐個的插入中完成的。
但這個插入還和插入操作的插入不一樣,那個插入是在目標位置,而這個插入是在表的末尾(雖然迴圈連結串列沒有什麼開始結束之類的,但名義上的head和end還是有的)
//建立——插入資料 int insert_list(list *head){ int data; //插入的資料型別 printf("請輸入要插入的元素:"); scanf("%d",&data); list *node=initlist(); node->data=data; //初始化一個新的結點,準備進行連結 if(head!=NULL){ list *p=head; //找到最後一個數據 while(p->next!=head){//① p=p->next; } p->next=node; node->next=head; return 1; }else{ printf("頭結點已無元素\n"); return 0; } } //①前面的單鏈表和雙向連結串列通過NULL找到連結串列的結尾,而迴圈連結串列通過連結串列頭next的地址head找到連結串列名義上的結尾。迴圈連結串列也正是通過這種方法實現在連結串列所謂結尾的插入。
3.4插入新結點
//插入元素
list *insert_list(list *head,int pos,int data){
//三個引數分別是連結串列,位置,引數
list *node=initlist(); //新建結點
list *p=head; //p表示新的連結串列
list *t;
t=p;
node->data=data;
if(head!=NULL){
for(int i=1;i<pos;i++){
t=t->next; //走到需要插入的位置處
}
node->next=t->next;
t->next=node;
return p;
}
return p;
}
3.5刪除結點
//刪除元素
int delete_list(list *head) {
if(head == NULL) {
printf("連結串列為空!\n");
return 0;
}
//建立臨時結點儲存頭結點資訊(目的為了找到退出點)
//如果不這麼建立的化需要使用一個數據進行計數標記,計數達到連結串列長度時自動退出
//迴圈連結串列當找到最後一個元素的時候會自動指向頭元素,這是我們不想讓他發生的------①
list *temp = head; //此時temp指向頭結點
list *ptr = head->next; //此時ptr指向頭結點的下一個節點
int del;
printf("請輸入你要刪除的元素:");
scanf("%d",&del);
while(ptr != head) {
if(ptr->data == del) {
if(ptr->next == head) { //判斷刪除節點是否為尾結點
temp->next = head;
free(ptr);
return 1; //跳出迴圈
}
temp->next = ptr->next; //核心刪除操作程式碼
free(ptr); //說明了ptr是目標刪除結點。
//printf("元素刪除成功!\n");
return 1;
}
temp = temp->next;
ptr = ptr->next; //標準的遍歷操作。
}c
printf("沒有找到要刪除的元素\n");
return 0;
}
//觀察前面的連結串列就能明白是什麼意思。前面連結串列用while和NULL判斷迴圈並退出,而迴圈列表沒有NULL。為了避免死迴圈,我們需要採用其他策略——例如利用連結串列頭的地址當作迴圈條件判斷跳出迴圈,當然也可以用程式碼註釋中說的計數器來判斷終止迴圈。
3.6迴圈連結串列的遍歷
//遍歷元素
int display(list *head) {
if(head != NULL) {
list *p = head;
//遍歷頭節點到,最後一個數據
while(p->next != head ) {
printf("%d ",p->next->data);
p = p->next;
}
printf("\n"); //習慣性換行 ( o=^•ェ•)o ┏━┓
//把最後一個節點賦新的節點過去
return 1;
} else {
printf("頭結點為空!\n");
return 0;
}
}
//關鍵還是找到合適的終止迴圈條件。目前已知的就是計數器和連結串列頭地址。
3.7完整的迴圈連結串列程式碼
#include<stdio.h>
#include<stdlib.h>
typedef struct list{
int data;
struct list *next;
}list;
//data為儲存的資料,next指標為指向下一個結點
//初始結點
list *initlist(){
list *head=(list*)malloc(sizeof(list));
if(head==NULL){
printf("建立失敗,退出程式");
exit(0);
}else{
head->next=NULL;
return head;
}
}
//建立--插入資料
int create_list(list *head){
int data; //插入的資料型別
printf("請輸入要插入的元素:");
scanf("%d",&data);
list *node=initlist();
node->data=data;
//初始化一個新的結點,準備進行連結
if(head!=NULL){
list *p=head;
//找到最後一個數據
while(p->next!=head){
p=p->next;
}
p->next=node;
node->next=head;
return 1;
}else{
printf("頭結點已無元素\n");
return 0;
}
}
//插入元素
list *insert_list(list *head,int pos,int data){
//三個引數分別是連結串列,位置,引數
list *node=initlist(); //新建結點
list *p=head; //p表示新的連結串列
list *t;
t=p;
node->data=data;
if(head!=NULL){
for(int i=1;i<=pos;i++){
t=t->next;
}
node->next=t->next;
t->next=node;
return p;
}
return p;
}
//刪除元素
int delete_list(list *head) {
if(head == NULL) {
printf("連結串列為空!\n");
return 0;
}
//建立零時結點儲存頭結點資訊(目的為了找到退出點)
//如果不這麼建立的化需要使用一個數據進行計數標記,計數達到連結串列長度時自動退出
//迴圈連結串列當找到最後一個元素的時候會自動指向頭元素,這是我們不想讓他發生的
list *temp = head;
list *ptr = head->next;
int del;
printf("請輸入你要刪除的元素:");
scanf("%d",&del);
while(ptr != head) {
if(ptr->data == del) {
if(ptr->next == head) { //迴圈結束的條件換成ptr->next == head
temp->next = head;
free(ptr);
return 1;
}
temp->next = ptr->next;
free(ptr);
//printf("元素刪除成功!\n");
return 1;
}
temp = temp->next;
ptr = ptr->next;
}
printf("沒有找到要刪除的元素\n");
return 0;
}
//遍歷元素
int display(list *head) {
if(head != NULL) {
list *p = head;
//遍歷頭節點到,最後一個數據
while(p->next != head ) {
printf("%d ",p->next->data);
p = p->next;
}
printf("\n"); //習慣性換行 ( o=^•ェ•)o ┏━┓
//把最後一個節點賦新的節點過去
return 1;
} else {
printf("頭結點為空!\n");
return 0;
}
}
int main(){
//////////初始化頭結點//////////////
list *head=initlist();
head->next=head;
////////通過插入元素完善連結串列/////////
for(int i=0;i<5;i++){ //只是演示使用,不具體提供輸入
create_list(head);
}
display(head);
////////////插入元素////////////////
head=insert_list(head,1,10);
display(head);
////////////刪除元素////////////////
delete_list(head);
display(head);
return 0;
}