#include<iostream>
#include<iomanip>
using namespace std;
//c++中默認的格式,在iomanip這個頭檔案中,io表示輸出,manip是manipulator(操縱器)的縮寫(在c++中只能通過輸入縮寫才有效))
typedef struct Lnode
{
int data;
Lnode *next;
}Lnode,*Linklist;//相當于typedef struct Lnode Lnode與typedef struct Lnode *Linklist兩條陳述句,且結點中資料是整形,指標是結點型別,
void createlist(Linklist &L,int n)//對頭指標L使用參考,無需return直接可以回傳L的值,還有一個形參n用來接收用戶傳來的值
{
L=new Lnode();//申請一個結點的記憶體空間并且讓頭指標L指向它
L->next=NULL;//頭指標指向的指標域為空
cout<<"輸入該表的資料:"<<endl;//當主函式呼叫該函式時,執行到此是會輸出這幾個漢字
for(int i=1;i<=n;i++)//使用一個for回圈,逐個插入資料
{
Linklist p=new Lnode;//申請一個結點空間并且用結點型指標變數p指向它
cin>>p->data;//用戶輸入資料傳到結點的資料域中
p->next=L->next;//把頭結點后面一個結點的地址傳到剛申請結點的指標域中,即把剛申請的結點指向緊鄰著頭結點的下一個結點,使用的是前插法
L->next=p;//把剛創建結點的地址放到首結點的地址域中
}
}
void displist(Linklist L)//這個函式的主要作用是把剛才使用前插法創建的單鏈表輸出
{
Linklist p=L->next;//定義一個指標變數p,并且它指向單鏈表L的首元結點
while(p)//當p所指向的結點不是NULL的時候則執行下面的回圈
{
cout<<"->"<<p->data;//當執行這個回圈的時候每回圈一次要輸出->和p所指向的資料
p=p->next;//p指向下一個結點,
}//執行完一次回圈之后會輸出一個->和一個結點中的資料,以及p會指向下一個結點則在輸出最后一個結點的資料之后,p所指向的為NULL,回圈結束,
}
bool listinsert(Linklist &L,int i,int e)//bool型說明在函式呼叫這個函式之后的回傳值要么是true,要么是false.括號中的都是形參,頭指標L采用了參考,整型變數i和e用來接收用戶傳來的資料,
{
Linklist p=L;int j=0;//定義了結點型指標變數p,并且與L的指向相同,它們兩個同時指向頭結點,并且定義整形變數j的值等于0.
while(p&&j<i-1)//在這里while回圈的條件是結點型指著變數所指向的結點不為空的時候并且j小于i-1的時候回圈繼續執行,這個回圈的目的是為了將結點型指標變數p指向第i-1結點的位置,
{
p=p->next;//回圈進來以后首先將p指向p的下一個結點,
j++;//j的值自增1.
}//這個回圈的目的就是讓p和j一齊后移增大,不斷地靠近條件的邊界,
if(!p||j>i-1)//這個if陳述句的判斷條件是如果p指向的結點為慷訓者j大于i-1的值,這兩個條件有一個滿足就會執行該if陳述句,
{
cout<<"i is error!";//如果i的值是負數,或者i-1的值大于單鏈表的長度,即都是用戶輸入i值得錯誤將會導致插入失敗,會提醒i is error!
return false;
}//該if陳述句的主要作用就是為了給出來一個信號以及使演算法的健壯性得以體現,如果i的值用戶輸入了-1則會提醒出錯了,如果p的值為空了同樣也會輸出去i的值是錯誤的,p指向的結點為空表示p已經指向表尾了還沒指向i-1的位置,說明i-1的值過大,j>i-1說明用戶輸入i的值是負數,
Linklist s=new Lnode();//在i的值既不是負數又部超出鏈表的長度范圍時即開始執行以下操作,申請一個新的結點空間并用結點型指標變數s指向它,
s->data=https://www.cnblogs.com/SuperAx/p/e;//剛申請新結點的資料域為e
s->next=p->next;//由于p指向的是i-1的結點,則p指向的下一個結點是i的結點,即把i的結點位置放到新結點的指標域內,即將要插入的結點指向第i個結點,
p->next=s;//把新結點的位置放到第i-1個結點的指標域內,即第i-1個結點指向將要插入的新結點s
return true;//在這一切完成以后回傳true,說明插入成功,插入失敗則是因為i的原因,
}
bool listdelete(Linklist &L,int m)//創建一個洗掉結點的函式,用于洗掉指定的結點
{
Linklist p=L;int j=0;//定義一個結點型指標變數p指向頭結點,并且定義一個整形變數j等于0.
while(p&&j<m-1)//引進一個while回圈,回圈的判斷條件是p不為空,以及j的值要小于i-1這樣回圈才會繼續執行下去,
{
p=p->next;//無論實在插入函式或是洗掉函式中,一進入while回圈,結點型指標變數p就指向下一個結點,這是因為單向鏈表只能對后面的結點進行操作,所以每次只能尋找到i-1項,
j++;//在插入和洗掉操作中while回圈的作用都是為了使結點型指標變數p指向第i-1個結點,
}
if(!p||j>m-1)//if陳述句的判斷條件是p的值非慷訓者輸入i的值為負數
{
cout<<"i is error!";//如果該if陳述句成立,說明要么p指向結點的值為空,這時說明i-1的值大于該單鏈表的長度即用戶輸入的i值過大,如果j>i-1成立說明用戶輸入i的值為負數,
return false;
}//總的來說,在插入洗掉操作中前兩步操作呼叫while回圈以及if回圈陳述句都是相同的,看看用戶傳來的i值是否符合這個單鏈表,而且他們的作用都是為了使結點型指標變數p指向第i-1個結點,
Linklist q=p->next;//目的是洗掉第i個結點,先定義一個結點型指標變數q指向第i個結點,即保存第i個結點的地址,
p->next=q->next;//由于q的下一個結點是第i+1個結點,放在左邊的p->next表示把右邊的地址當道p的指標域中,由于p指向的是第i-1個結點,即把第i+1個結點的地址放到第i-1的指標域中,最終目的使第i-1的結點指向i+1;
delete q;//洗掉q指向的結點,即洗掉第i個結點,當結點型指標變數單個出現時表示的是這個指標所指向的結點,
return true;//如果執行到這一步說明洗掉操作已經結束,回傳給操作者一個正確的回應true.
}
int main()//主函式,后面沒有冒號,沒有回傳值
{
int n; Linklist L;//定義一個整形變數n,以及一個結點型指標變數L,也就是頭指標,
cout<<"請輸入鏈表的長度:"<<endl;//編譯后會輸出“請輸入鏈表的長度這句話”,但cin卻看不到
cin>>n;//從鍵盤輸入n的值,
createlist(L, n);//呼叫函式就更加簡單了,直接把函式名以及后面的形參串列復制過來,刪去形參的型別即可,
displist(L);//先創建單鏈表,后輸出單鏈表
int i,e;
cout<<"請輸入插入的位置和數值:"<<endl;
cin>>i>>e;
listinsert(L, i, e);
displist(L);//在呼叫函式之前要在主函式中先定義函式中需要用到的變數,并且用cout輸出,接下來用cin從鍵盤中輸入剛才定義變數的值,
int m;
cout<<"請輸入洗掉的位置:";
cin>>m;
listdelete(L,m);
displist(L);
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/33842.html
標籤:其他
上一篇:0334. Increasing Triplet Subsequence (M)
下一篇:ICPC Pacific Northwest Regional Contest 2016 Maximum Islands(二分圖最大獨立集)
