动态游标for循环_数据结构系列循环链表
前面留的一個(gè)問題,后文更跟新回答
????單鏈表可以表示任意的線性關(guān)系,有些線性關(guān)系是循環(huán)的,既沒有隊(duì)尾元素。
????將單鏈表中的終端結(jié)點(diǎn)指針端由空指針改為指向頭結(jié)點(diǎn),這時(shí)的單鏈表形成國(guó)恒一個(gè)環(huán),改為循環(huán)鏈表。
????插入與刪除與單鏈表的原理甚至一模一樣,工程CircleListPro,將單鏈表改成循環(huán)鏈表。
CircleList.h文件
ifndef _CIRCLELIST_H_#define?_CIRCLELIST_H_typedef void CircleList;typedef struct _tag_CircleListNode CircleListNote;struct _tag_CircleListNode{ CircleListNode* next; }CircleList* CircleList_Creat(int capacity);void CircleList_Destory(CircleList* list);void CircleList_Clear(CircleList* list);int?CircleList_Length(CircleList*?list);int CircleList_Insert(CircleList* list,CircleListNode* node,int pos);CircleListNode* CircleList_Get(CircleList* list,int pos);CircleListNode* CircleList_Delete(CircleList* list,int pos);#endifCiecleList.c
#include #include #include "CircleList.h"#define AVAILABLE -1//空閑位置的宏//靜態(tài)鏈表結(jié)構(gòu)體定義typedef struct _tag_CircleList{ CircleListNode header;//鏈表頭 int length;}TCircleList; CircleList*?CircleList_Create()//o(1){??TCircleList*?ret?=?(TCircleList*)malloc(sizeof(TCircleList));?? if(ret != NULL)//指針不為0時(shí)可以繼續(xù)賦值操作 { ??ret->length?=?0; ret->header.next = NULL;????} return ret;}void CircleList_Destory(CircleList* list){ free(list);}void CircleList_Clear(CircleList* list) //o(1){ TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 ? if(sList != NULL)//鏈表不為空是合法的,可以繼續(xù)清空操作 { sList->length = 0; sList->header.next = NULL;//第一個(gè)元素下標(biāo)沒有了????}}int CircleList_Length(CircleList* list)//o(1){ TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 int ret = -1;//定義一個(gè)返回值 if(sList !=NULL)//鏈表不為空是合法的,可以繼續(xù)清空操作 { ret = sList->length; } return ret;}//?插入時(shí),如果表頭是空的指向NULL,元素是空的,進(jìn)行單鏈表元素插入時(shí),現(xiàn)將插入元素// 尾結(jié)點(diǎn)與NULL相連,再把插入元素?cái)?shù)據(jù)與前結(jié)點(diǎn)相連,再把該節(jié)點(diǎn)next與自己相連,去除原來NULL,構(gòu)成循環(huán)鏈表int?CircleList_Insert(CircleList*?list,CircleListNode*?node,int?pos)//o(n)n是插入元素的位置·{ TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 ??int?ret?=(sList?!=NULL)&& (pos?>=0)?&& (node?!= NULL);//單鏈表方法完成判斷 int i=0; if(ret)//在數(shù)組中找空閑位置index {??CircleListNode*?current?= (CircleListNode*)sList;????for(i?=?0;(inext != NULL);?i++) { current = current->next; } ??node->next = current->next;??current->next = node;????if(sList->length?==?0)//?插入的元素是第一個(gè),length的值為0??{?? node->next = node;// 新元素node的next指針指向自己??}????sList->length++ ;}return ret;}CircleListNode* CircleList_Get(CircleList* list,int pos)// o(n){TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 CircleListNode*?ret?=?NULL;//定義一個(gè)返回值int i = 0;if((sList?!=?NULL)?&&(0?<=?pos)//鏈表不為空是合法的,長(zhǎng)度正常,與單鏈表不同的是不需要pos { CircleListNode*?current?=?(CircleListNode*)sList; for(i=0;i { current = current->next;//第一個(gè)元素所在下標(biāo) } ret = current->next; }return ret;}//獲取第pos個(gè)元素,將第pos個(gè)元素從鏈表里刪除//特殊的刪除第一個(gè)元素,除了將表頭next移到第二個(gè)元素之外,還要將最后一個(gè)next移到第二個(gè)nextCircleListNode*?CircleList_Delete(CircleList*?list,int?pos)//o(n){ TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 CircleListNode*?ret?=?NULL;//定義一個(gè)返回值 int i = 0; if(?(sList?!=NULL)?&& (0?<=?pos)?)//鏈表不為空是合法的,長(zhǎng)度正常 { CircleListNode*?current?=?(CircleListNode*)sList;????CircleListNode*?first?=?sList->header.next;//?標(biāo)記第一個(gè)元素 CircleListNode*?last?=?(CircleListNode*)CircleList_Get(sList,sList->length - 1); // 由get函數(shù)得到最后一個(gè)元素 for(i=0;i { current = current->next;//第一個(gè)元素所在下標(biāo) } ret = current->next; current->next?=?ret->next; sList->length--; ????if(first?==?ret)//?判斷刪除元素是否是原來表頭,first指針與原來ret指針是否是同一個(gè) { ????sList->header.next?=?ret->next;// 將表頭指向ret????????last->next?=?ret->next;//?指針移動(dòng)到原來的第二個(gè)元素 } ??????if(sList->length?==?0)//?如果鏈表空了則前面操作沒有意義??????{?????? sList->header.next = NULL;// 復(fù)原??????} } return ret;}main.c
#include #include #include??"CircleList.h"//自己創(chuàng)建的文件,而不是系統(tǒng)文件用雙引號(hào)struct?Value{??CircleListNode?header;//?定義域 int v;// 真正保存數(shù)據(jù)的域}int main(int argc,char *argv[]){ int i = 0; CircleList*??list?=?CircleList_Create(); struct Value v1; struct Value v2; struct Value v3; struct Value v4; struct Value v5; struct Value v6; struct Value v7; struct Value v8; v1.v = 1 ; v2.v = 2 ; v3.v = 3 ; v4.v = 4 ; v5.v = 5 ;??v6.v?=?6?;??v7.v?=?7?; v8.v = 8 ; // 尾插法,插入到最后一個(gè)元素后面??CircleList_Insert(list,(?CircleListNode*)&V1,?CircleList_Length(list));?????????????CircleList_Insert(list,(?CircleListNode*)&V2,?CircleList_Length(list));???CircleList_Insert(list,(?CircleListNode*)&V3,?CircleList_Length(list));???CircleList_Insert(list,(?CircleListNode*)&V4,?CircleList_Length(list));?????CircleList_Insert(list,(?CircleListNode*)&V5,5);??CircleList_Delete(list,0); ?// 證明是循環(huán)鏈表,刪除第一個(gè)元素,循環(huán)兩遍 ??for(i=0;i?2*CircleList_Length( ??{ ????struct?Value*?pv?=?(struct?Value*)?CircleList_Get(list,i) ????printf("%d\n",pv->v); ??}????printf("\n");????while( CircleList_Length(list) > 0)// 循環(huán)鏈表還有元素從頭開始刪????{ ????struct Value* pv = (struct Value*) CircleList_Delete(list,0); ????printf("%d\n",pv->v); } CircleList_Destory(list); return 0;}????為了體現(xiàn)循環(huán)鏈表的威力,引入游標(biāo):在循環(huán)鏈表中定義一個(gè)“當(dāng)前”指針,這個(gè)指針通常稱為游標(biāo),可以通過這個(gè)游標(biāo)來遍歷鏈表中所有元素。
加了游標(biāo)新操作CircleList.h文件
#ifndef _CIRCLELIST_H_#define?_CIRCLELIST_H_typedef void CircleList;typedef struct _tag_CircleListNode CircleListNote;struct _tag_CircleListNode{ CircleListNode* next; }CircleList* CircleList_Creat(int capacity);void CircleList_Destory(CircleList* list);void CircleList_Clear(CircleList* list);int?CircleList_Length(CircleList*?list);int CircleList_Insert(CircleList* list,CircleListNode* node,int pos);CircleListNode* CircleList_Get(CircleList* list,int pos);CircleListNode* CircleList_Delete(CircleList* list,int pos);//?加入游標(biāo)新操作//?獲取當(dāng)前游標(biāo)指向的數(shù)據(jù)元素,可以刪除鏈表里某個(gè)數(shù)據(jù)元素,不需要先得到所要?jiǎng)h除的數(shù)據(jù)下標(biāo)CircleListNode* CircleList_DeleteNode(CircleList* list,CircleListNode* node);//?將游標(biāo)重置指向鏈表中的第一個(gè)元素CircleListNode*?CircleList_Resert(CircleList*?list);// 將游標(biāo)移動(dòng)到鏈表的下一個(gè)數(shù)據(jù)元素CircleListNode*?CircleList_Current(CircleList*?list);// 直接刪除鏈表中某個(gè)數(shù)據(jù)元素CircleListNode* CircleList_Next(CircleList* list);#endif#include #include #include "CircleList.h"#define AVAILABLE -1//空閑位置的宏//靜態(tài)鏈表結(jié)構(gòu)體定義typedef struct _tag_CircleList{ CircleListNode header;//鏈表頭??CircleListNode*?sLidrer;// 定義游標(biāo) int length;}TCircleList; CircleList* CircleList_Create()//o(1){ TCircleList* ret = (TCircleList*)malloc(sizeof(TCircleList)); if(ret != NULL)//指針不為0時(shí)可以繼續(xù)賦值操作 { ret->length = 0; ret->header.next = NULL; ret->slider = NULL;// 在循環(huán)鏈表創(chuàng)建的時(shí)候,沒有元素,游標(biāo)定義為空 } return ret;}void CircleList_Destory(CircleList* list){ free(list);}void CircleList_Clear(CircleList* list) //o(1){ TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 if(sList != NULL)//鏈表不為空是合法的,可以繼續(xù)清空操作 { sList->length = 0; sList->header.next = NULL;//第一個(gè)元素下標(biāo)沒有了??????sList->slider??=?NULL;//?循環(huán)鏈表重置為復(fù)原狀態(tài)。游標(biāo)也重置為空 }}int CircleList_Length(CircleList* list)//o(1){ TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 int ret = -1;//定義一個(gè)返回值 if(sList !=NULL)//鏈表不為空是合法的,可以繼續(xù)清空操作 { ret = sList->length; } return ret;}// 插入時(shí),如果表頭是空的指向NULL,元素是空的,進(jìn)行單鏈表元素插入時(shí),現(xiàn)將插入元素// 尾結(jié)點(diǎn)與NULL相連,再把插入元素?cái)?shù)據(jù)與前結(jié)點(diǎn)相連,再把該節(jié)點(diǎn)next與自己相連,去除原來NULL,構(gòu)成循環(huán)鏈表int CircleList_Insert(CircleList* list,CircleListNode* node,int pos)//o(n)n是插入元素的位置·{ TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 int ret =(sList !=NULL)&& (pos >=0) && (node != NULL);//單鏈表方法完成判斷 int i=0; if(ret)//在數(shù)組中找空閑位置index { CircleListNode* current = (CircleListNode*)sList; for(i = 0;(inext != NULL); i++) { current = current->next; } node->next = current->next; current->next = node; if(sList->length == 0)// 插入的元素是第一個(gè),length的值為0 {????slider->slider = node;//?游標(biāo)指向插入的第一個(gè)結(jié)點(diǎn) node->next = node;// 游標(biāo)默認(rèn)初始位置為0,新元素node的next指針指向自己 } sList->length++ ;}return ret;}CircleListNode* CircleList_Get(CircleList* list,int pos)// o(n){ TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 CircleListNode* ret = NULL;//定義一個(gè)返回值 int i = 0; if((sList != NULL) &&(0 <= pos)//鏈表不為空是合法的,長(zhǎng)度正常,與單鏈表不同的是不需要pos { CircleListNode* current = (CircleListNode*)sList; for(i=0;i { current = current->next;//第一個(gè)元素所在下標(biāo) } ret = current->next; } return ret;}//獲取第pos個(gè)元素,將第pos個(gè)元素從鏈表里刪除//特殊的刪除第一個(gè)元素,除了將表頭next移到第二個(gè)元素之外,還要將最后一個(gè)next移到第二個(gè)nextCircleListNode* CircleList_Delete(CircleList* list,int pos)//o(n){ TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 CircleListNode* ret = NULL;//定義一個(gè)返回值 int i = 0; if( (sList !=NULL) && (0 <= pos) )//鏈表不為空是合法的,長(zhǎng)度正常 { CircleListNode* current = (CircleListNode*)sList; CircleListNode* first = sList->header.next;// 標(biāo)記第一個(gè)元素 CircleListNode* last = (CircleListNode*)CircleList_Get(sList,sList->length - 1); // 由get函數(shù)得到最后一個(gè)元素 for(i=0;i { current = current->next;//第一個(gè)元素所在下標(biāo) } ret = current->next; current->next = ret->next; sList->length--; if(first == ret)// 判斷刪除元素是否是原來表頭,first指針與原來ret指針是否是同一個(gè) { sList->header.next = ret->next;// 將表頭指向ret last->next = ret->next;// 指針移動(dòng)到原來的第二個(gè)元素 } if(slider->slider == ret)// SLIDER指向的元素和要?jiǎng)h除的元素指針一致 {????????sList->slider?=?ret->next?;//?slider指向ret的下一個(gè)元素 } if(sList->length == 0)// 如果鏈表空了則前面操作沒有意義 { sList->header.next = NULL;// 復(fù)原????????sList->slider?=?NULL;//?刪除的元素剛好為鏈表最后一個(gè)元素,游標(biāo)復(fù)原為空 } } return ret;}//?獲取當(dāng)前游標(biāo)指向的數(shù)據(jù)元素,刪除對(duì)應(yīng)的CircleListNode*?node這個(gè)元素o(n0CircleListNode*?CircleList_DeleteNode(CircleList*?list,CircleListNode*?node){// 該做的檢測(cè)正常做 TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 CircleListNode* ret = NULL;//定義一個(gè)返回值 int i = 0; if (sList != NULL)???{??? CircleListNode* current = (CircleListNode*)sList;// 做移動(dòng),查找node在循環(huán)鏈表的邏輯位置 for(i=0;ilength;i++) { ??????if(current->next == node) ??????{ ?????? ret =current->next; ?????? break; ??????} ?????? current = current->next; ??????} ???????if(ret?!=?NULL )// 找不到,非法元素 ???????{???????????????circleList_Delete(sList,i);//?i就是所找到的刪除位置,調(diào)用delete刪除即可 ???????}?? ?} return ret;}CircleListNode*?CircleList_Resert(CircleList*?list)// o(1)將游標(biāo)重置指向鏈表中的第一個(gè)元素{// 該做的檢測(cè)正常做 TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 CircleListNode* ret = NULL;//定義一個(gè)返回值 if(sList != NULL ) { ???slist->slider?=?sList->header.next;// slider重置到第一個(gè)元素 ???ret = sList->slider?;// 返回判斷重置是否成功???}???return ret;}CircleListNode*?CircleList_Current(CircleList*?list)//? o(1)將游標(biāo)移動(dòng)指向到鏈表中的下一個(gè)數(shù)據(jù)元素{// 該做的檢測(cè)正常做 TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 CircleListNode* ret = NULL;//定義一個(gè)返回值 if(sList != NULL )??{ ret = sList->slider ; } return ret; }CircleListNode*?CircleList_Next(CircleList*?list)// o(1)直接刪除鏈表中的某個(gè)數(shù)據(jù)元素?{//?該做的檢測(cè)正常做 TCircleList* sList = (TCircleList*)list;//用到了數(shù)據(jù)封裝,所以強(qiáng)制類型轉(zhuǎn)換 CircleListNode* ret = NULL;//定義一個(gè)返回值??//?當(dāng)前游標(biāo)指向下一個(gè)元素????if((sList?!=?NULL?)?&&?(sList->slider != NULL )) { ret = sList->slider ;// 在移動(dòng)之前把當(dāng)前值保存作為返回值返回?????sList->slider = ret->next;// 真正移動(dòng) } return ret;}循環(huán)鏈表的應(yīng)用:約瑟夫問題
??? n個(gè)人圍成一個(gè)圓圈,首先從第一個(gè)人從1開始報(bào)數(shù),報(bào)到第m個(gè)人,令其出列;然后再?gòu)南乱粋€(gè)人繼續(xù)報(bào)數(shù),報(bào)到第m個(gè)人,再另其出列……如此下去,求其出列順序。?
main.c
#include #include #include??"CircleList.h"//自己創(chuàng)建的文件,而不是系統(tǒng)文件用雙引號(hào)struct?Value{??CircleListNode?header;//?定義域 int v;// 真正保存數(shù)據(jù)的域}int main(int argc,char *argv[]){ int i = 0; CircleList*??list?=?CircleList_Create(); struct Value v1; struct Value v2; struct Value v3; struct Value v4; struct Value v5; struct Value v6; struct Value v7; struct Value v8; v1.v = 1 ; v2.v = 2 ; v3.v = 3 ; v4.v = 4 ; v5.v = 5 ;??v6.v?=?6?;??v7.v?=?7?; v8.v = 8 ; // 尾插法,插入到最后一個(gè)元素后面??CircleList_Insert(list,(?CircleListNode*)&V1,?CircleList_Length(list));?????????????CircleList_Insert(list,(?CircleListNode*)&V2,?CircleList_Length(list));???CircleList_Insert(list,(?CircleListNode*)&V3,?CircleList_Length(list));???CircleList_Insert(list,(?CircleListNode*)&V4,?CircleList_Length(list));?????CircleList_Insert(list,(?CircleListNode*)&V5,5);??CircleList_Delete(list,0); ?// 證明是循環(huán)鏈表,刪除第一個(gè)元素,循環(huán)兩遍 ??for(i=0;i?2*CircleList_Length( ??{ ????struct?Value*?pv?=?(struct?Value*)?CircleList_Get(list,i) ????printf("%d\n",pv->v); ??}????printf("\n");????while( CircleList_Length(list) > 0)// 循環(huán)鏈表還有元素從頭開始刪????{ ????struct Value* pv = (struct Value*) CircleList_Delete(list,0); ????printf("%d\n",pv->v); } printf("\n"); CircleList_Insert(list,( CircleListNode*)&V1, CircleList_Length(list)); CircleList_Insert(list,( CircleListNode*)&V2, CircleList_Length(list)); CircleList_Insert(list,( CircleListNode*)&V3, CircleList_Length(list)); CircleList_Insert(list,( CircleListNode*)&V4, CircleList_Length(list)); ??CircleList_Insert(list,(?CircleListNode*)&V5,?CircleList_Length(list));??????????? CircleList_Insert(list,( CircleListNode*)&V6, CircleList_Length(list)); CircleList_Insert(list,( CircleListNode*)&V7, CircleList_Length(list)); CircleList_Insert(list,( CircleListNode*)&V8, CircleList_Length(list)); for(i=0;i < CircleList_Length(list);i++)// 查看八個(gè)人是否在循環(huán)鏈表中 { ??????struct?Value*?pv?=?(struct?Value*)?CircleList_Next(list) ??????//?先將當(dāng)前的返回再移動(dòng) printf("%d\n",pv->v); } printf("\n"); CircleList_Resert(list); // 重置游標(biāo) // 解決約瑟夫問題 ?????while(?CircleList_Length(list)?>?0)//?當(dāng)鏈表中沒有元素的時(shí)候停止出列 { ???struct Value* pv = NULL; ???for(i = 1;i < 3;i++) ???{?????????????CircleList_Next?(list);//?這里的移動(dòng)用游標(biāo)來移動(dòng),所以很高效 ???} ??pv = (struct Value*) CircleList_Current(list); ??printf("%d\n",pv->v); ???CircleList_DeleteNode(list,(CircleListNode*) pv ); } CircleList_Destory(list); return 0;}小結(jié);
循環(huán)鏈表只是在單鏈表的基礎(chǔ)上做了一個(gè)加強(qiáng)
循環(huán)鏈表完全可以代替單鏈表
循環(huán)鏈表的Next和Current操作可以高效的遍歷鏈表中的每個(gè)元素
總結(jié)
以上是生活随笔為你收集整理的动态游标for循环_数据结构系列循环链表的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谷歌tts android手机自带引擎,
- 下一篇: java hs err pid_JAVA