手機(jī)網(wǎng)站用單獨做嗎列舉常見的網(wǎng)絡(luò)營銷工具
帶頭雙向循環(huán)鏈表的基本操作
- 結(jié)構(gòu)體定義
- 初始化
- 創(chuàng)建新節(jié)點
- 頭插
- 頭刪
- 尾插
- 尾刪
- 查找
- 在指定位置之后插入
- 刪除指定位置的值
- 打印
結(jié)構(gòu)體定義
typedef int DataType;
typedef struct LinkNode
{DataType data;struct LinkNode* prev;struct LinkNode* next;
}LNode;
初始化
有兩種初始化方式
第一種你需要在main函數(shù)里或者全局定義一個LNode* phead,注意,只需要定義就可以了,然后再調(diào)用Init(&phead);
為什么要傳地址呢?
因為在Init函數(shù)內(nèi)部我們需要對phead進(jìn)行操作(分配空間),那么一旦需要對參數(shù)進(jìn)行操作,那就不能只穿本身,而要傳地址。
void Init(LNode** pphead)
{*pphead=(LNode*)malloc(sizeof(LNode));(*pphead)->data=-1;(*pphead)->next=(*pphead)->prev=*pphead;
}
這一種的話,不需要在main函數(shù)里創(chuàng)建,直接調(diào)用Init_1()函數(shù)就行。
void Init_1()
{LNode* phead=(LNode*)malloc(sizeof(LNode));phead->data=-1;phead->prev=phead->next=phead;
}
初始化以后,頭結(jié)點就是這樣子了:
創(chuàng)建新節(jié)點
函數(shù)參數(shù)為DataType類型
LNode* CreateNode(DataType x)
{LNode* newnode=(LNode*)malloc(sizeof(LNode));newnode->prev=newnode->next=NULL;//這個地方也將prev和next初始化為newnode自身//因為這兩個指針后續(xù)都會改變方向,因此初始狀態(tài)無所謂。return newnode;
}
頭插
這里的頭插指的是在第一個有效節(jié)點之前插入,也就是插入到head的后一個。
我們第一步先把新節(jié)點的prev和next設(shè)置好,因為這樣做不影響鏈表結(jié)構(gòu),肯定先把簡單的搞了嘛~
然后再修改head->next和head->next->prev(圖中1號節(jié)點)的指向,至于這兩個誰先誰后,那就無所謂了。
頭插完以后就是這個樣子了
void PushHead(LNode* phead,DataType x)
{LNode* new=CreateNode(x);new->next=phead->next;new->prev=phead;phead->next->prev=new;phead->next=new;
}
頭刪
頭刪需要注意的一個點就是判斷是否只剩下了一個節(jié)點,有些題目會要求頭刪直至為NULL,有的會要求刪到只剩最后一個,我們這里以后者為例
先這么改
再這么改(這兩步順序可以變)
最后再釋放掉new節(jié)點就可以了(當(dāng)然考試的時候不釋放也行,平時養(yǎng)成這個習(xí)慣還是很好的!)
void DelHead(LNode* phead)
{if(phead->next==phead)return;else{LNode* tmp=phead->next;phead->next=tmp->next;tmp->next->prev=phead; free(tmp); }
}
尾插
尾插其實就是在頭結(jié)點的前一個插,所以簡單程度可想而知:
void PushBack(LNode*phead,DataType x)
{LNode*new=CreateNode(x);new->next=phead;new->prev=phead->prev;phead->prev->next=new;phead->prev=new;
}
尾刪
跟剛才尾插一個道理,就是頭結(jié)點的前一個。
void DelBack(LNode*phead)
{LNode* tmp=phead->prev;phead->prev=tmp->prev;tmp->prev->next=phead;free(tmp);
}
查找
查找的時候,有時候?qū)Σ檎业拈_始位置可能也有限制。如果是帶頭的雙循環(huán)鏈表比較好辦,如果是不帶頭的,如果要從phead開始查找,那么開始訪問位置cur就得是phead->prev;
我們這里介紹從phead的next開始訪問的情況,其他情況趨同,只需要改變初始訪問指針cur的值就可以
LNode* Find(LNode* phead,DataType x)
{LNode* cur=phead->next;while(cur!=phead){if(cur->data==x)return cur;cur=cur->next;}return NULL;
}
在指定位置之后插入
跟頭插簡直一模一樣,就是把參數(shù)換了個名兒
void Insert(LNode* pos,DataType x)
{LNode* new=CreateNode(x);new->next=pos;new->prev=pos->prev;pos->prev->next=new;pos->prev=new;
}
刪除指定位置的值
跟剛才頭刪尾刪一樣,有些題可能需要刪到最后一個為止
void DelPos(LNode* pos)
{if(pos->next=pos)return;else{LNode* front=pos->prev;LNode* after=pos->next;front->next=after;after->prev=front;}
}
打印
這個地方比較巧妙,如果想讓phead的值第一個被打印,那么循環(huán)就要用do while 因為如果用了while(cur!=phead),那么循環(huán)完全進(jìn)不去,因為訪問指針cur的初始值就為phead,用do while可以先執(zhí)行一次,執(zhí)行完之后cur的指向就不再是phead了,然后再判斷循環(huán)條件。
void Print(LNode* phead)
{LNode* cur=phead;do{printf("%d ",cur->data);cur=cur->next;} while (cur!=phead);}
有兩道非常好的雙向循環(huán)鏈表的題推薦給大家:
link
這是我寫的我們學(xué)校作業(yè)的題解,
空閑空間申請模擬和 ***文件加密!***這兩道題都用到了循環(huán)鏈表,但是比剛剛的基礎(chǔ)操作要復(fù)雜很多,但是基本的思想都是大差不差的,我在本文中提到的一些注意事項,在這兩道題中都有體現(xiàn),比如說開始訪問位置,判斷是否為空等等,大家如果想要提高一下可以去看看那兩道題哈~