1、鏈表:鏈表是一種物理存儲單元上非連續、非順序的存儲結構,數據元素的邏輯順序是通過鏈表中的指針鏈接次序實現的。鏈表由一系列結點(鏈表中每一個元素稱爲結點)組成,結點可以在運行時動態生成。每個結點包括兩個部分:一個是存儲數據元素的數據域,另一個是存儲下一個結點地址的指針域。
由於不必須按順序存儲,鏈表在插入的時候可以達到O(1)的複雜度,查找一個節點或者訪問特定編號的節點則需要O(n)的時間
2、鏈表的聲名與定義:
typedef struct node
{
int nval; //數據域
struct node *pnext; //指針域
}list;
3、鏈表的創建:
list *createnode()
{
list *phead = NULL;
list *pend = NULL;
list *ptmp = NULL;
int cnt ;
int n;
scanf("%d",&cnt);
while(cnt>0)
{
scanf("%d",&n);
ptmp = (list *)malloc(sizeof(list));
ptmp->nval = n;
ptmp->pnext = NULL;
if(phead == NULL)
{
phead = ptmp;
}
else
{
pend->pnext = ptmp;
}
pend = ptmp;
cnt--;
}
return phead;
}
4、鏈表的打印:鏈表的輸出可以是非遞歸的,也可以是遞歸的。
void outputnode(list *pnode) //非遞歸打印鏈表
{
while(pnode != NULL)
{
printf("%d ",pnode->nval);
pnode = pnode->pnext;
}
}
void diguioutputnode(list *pnode) //遞歸打印鏈表
{
if(pnode != NULL) //如果該節點不是空,那麼打印下一個
{
printf("%d ",pnode->nval);
diguioutputnode(pnode->pnext);
}
}
5.鏈表的逆序輸出問題:我給出三種方法:第一種是將鏈表輸入到數組中,再逆序輸出;第二種方法是遞歸逆序打印鏈表想法類似於順序遞歸打印;第三種方法是直接將原鏈表倒置。
void reverse_output(list *pnode) //方法一:輸入數組,逆序打印數組
{
if(pnode==NULL) return ;
int len = 0;
int i = 0;
list *pmark = pnode;
while(pmark!=NULL)
{
len++;
pmark = pmark->pnext;
}
int *p = (int *)malloc(sizeof(int)*len);
while(pnode != NULL)
{
p[i] = pnode->nval;
pnode = pnode->pnext;
i++;
}
for(i=len-1;i>=0;i--)
{
printf("%d ",p[i]);
}
free(p);
p = NULL;
}
list *reverse_list(list *phead) //方法二:將鏈表倒置
{
list *p1 = NULL;
list *p2 = phead;
list *p3 = phead->pnext;
while(p3!=NULL)
{
p2->pnext = p1;
p1 = p2;
p2 = p3;
p3 = p3->pnext;
}
p2->pnext = p1;
return p2;
}
void digui_reverseoutputlist(list *phead) //方法三:遞歸逆序鏈表
{
if(phead == NULL) //節點爲空不打印
{
return ;
}
else //節點不爲空打印下一個;最後打印當前節點。
{
digui_reverseoutputlist(phead->pnext);
printf("%d ",phead->nval);
}
}
對於方法二的實現解釋:
新建三個指針p2指向鏈表的頭節點,p3指向鏈表的頭節點的下一個節點(即phead->pnext),p1初值爲空,將三個指針作爲鏈表的三個節點順着鏈表移動,當中將每一個節點的指向下一個節點指針(即p2->pnext)賦值爲前一個節點(即p1)上。最後,要有一個p3作爲邊界條件,斷開後讓原鏈表的尾節點(p2)作爲新鏈表的頭,並且連接上新的鏈表,返回p2即可。
程序截圖: