大二學數據結構的時候沒好好做題,導致現在有關數據結構這方面的題做起來都比較費勁,就想着抽空重新自學一下。首先肯定是要先自學一下鏈表的建立,但是畢竟還是有一點基礎的。就不從頭插法尾插法開始學起了,我覺得能把這個雙向循環鏈表熟練的建立然後輸出出來正常的建一個單向,不管正向逆向應該都是信手拈來了。
自學的代碼如下(如果有什麼建議的話可以直接評論或私信我):
#include <bits/stdc++.h>
using namespace std;
struct node
{
int data; //存數據的位置
struct node *next; //指向下一個結點
struct node *last; //指向上一個結點
}*p, *q, *head; //head是鏈表的頭,p和q都是移動指針,p負責賦值用,q負責結點指向位置的確定
int main()
{
int n, m;
scanf("%d", &n);
m = n;
head = (struct node *)malloc(sizeof(struct node));
//head是鏈表的第一個元素;目的是找到鏈表所在,除它以外的指針都是移動的。
q = head; //q爲移動指針,指向我們要插入的元素的前一個,首先要等於head不然鏈表聯繫不起來
while(m--) //m個元素
{
p = (struct node *)malloc(sizeof(struct node)); //給剛出現的結點一個新的空間
scanf("%d", &p->data);
p -> next = NULL; //p的下一個結點還未出現,先賦成空,要明確每個指針指向的位置
q -> next = p; //q是p的上一個指針,那麼p是q的下一個指針,所以q的next指向p
p -> last = q; //q是p的上一個,所以p的last指向q
q = p; //當下一次建立新節點p時,才能保證每次p都是在上一個p的後面
}
/*
分析循環結束時的狀態:
p -> next = NULL; 說明最後一個結點的next是空。
p -> last = q; 說明最後一個結點的last指向上一個結點。
此時最後一個結點分析完了;
然後分析頭(head):第一次進入循環的時候有一個 q -> next = p; 第一次的q就是head;
所以head下一個指向整個鏈表的第一個帶data的結點(head自己不帶的)。
總結:最後一個結點next指向的空,head的last指向的不知道,因爲沒初始head->last = NULL;
*/
p -> next = head -> next; //最後一個結點的next指向第一個元素,此時正向便可以循環了。
head -> last = p; //head的上一個結點指向最後一個結點p
q = head -> next; //q此時待變第一個帶元素的結點
q -> last = head -> last; //第一個元素的last指向head的last也就是最後一個元素。此時逆向也可以循環了。
m = n*2;
while(m--)
{
printf("%d -> ", q->data);
q = q->next; //正向循環輸出兩遍這個鏈表,代表鏈表已接起來
}
q = head -> last;
printf("\n");
m = n *2;
while(m--)
{
printf("%d <- ", q->data);
q = q->last; //逆向循環輸出兩邊鏈表,代表逆向也連接正常,此時可證明雙向循環鏈表已經可以使用了,鏈表一共有n個元素。
}
return 0;
}
自學的時候畫個圖就會很清晰的。比如分析的時候,可以把分析結果用圖像的時候表示。
/*
分析循環結束時的狀態:
p -> next = NULL; 說明最後一個結點的next是空。
p -> last = q; 說明最後一個結點的last指向上一個結點。
此時最後一個結點分析完了;
然後分析頭(head):第一次進入循環的時候有一個 q -> next = p; 第一次的q就是head;
所以head下一個指向整個鏈表的第一個帶data的結點(head自己不帶的)。
總結:最後一個結點next指向的空,head的last指向的不知道,因爲沒初始head->last = NULL;
*/
目標就是:p的next指向head的next;head和head後面的結點的last指向p;
運行結果: