線性表:n個數據元素(A1,A2......An)的有限序列,大小爲0的表爲空表。
前驅:在非空表中我們稱A(i+1)是Ai前驅。
後繼:在非空表中我們稱A(i--1)是Ai後繼。
1.線性表的順序表示
用一組地址連續的順序存儲單元一次存儲線性表的數據元素。(通常使用數組來實現)
插入和刪除最壞情況都需要O(N)。
2.線性表的鏈式表示
1鏈表
鏈表由一系列不必在內存中相連的結構組成,每一個結構均含有表元素和指向包含該元素後繼元的結構指針。最後一個元素的後繼指針指向NULL。
該結構(又稱爲結點)由兩個域組成:數據域和指針域,數據域存儲數據元素信息,指針域存儲後繼結點的地址。
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
如果L爲LinkList型的變量,則L爲單鏈表的頭指針,它指向表中第一個結點。如果L爲空則表爲空。
有時候我們附設一個頭結點,數據域可以不存儲數據,也可以存儲如線性表長度等的附加信息,指針域存儲第一個結點的指針,稱之爲頭結點。
1.1 單鏈表的創建
單鏈表的創建一般有兩種方法:頭插法和尾插法。
頭插法從一個空表開始,創建新結點,將輸入的數據存放到新結點的數據域中,然後將新結點插入到當前鏈表的表頭上,直到結束爲止。簡單來說,就是把新加進的元素放在表頭後的第一個位置,如圖所示
代碼如下:
LinkList creatListHead(int n)
{
int i;
int e;
LinkList L,p;
//創建頭結點
L = (LinkList)malloc(sizeof(LNode));
L->next =NULL;
for(i=1;i<=n;i++)
{
p = (LinkList)malloc(sizeof(LNode));
scanf("%d",&e);
p->data = e;
p->next = L->next;
L->next = p;
}
return L;
}
尾插法從字面意思可以理解爲在表的最後插入結點。從一個空表開始,創建新結點,將輸入的數據存放到新結點的數據域中,然後將新結點插入到當前鏈表的表尾上,直到讀入結束標誌爲止。如圖所示
代碼如下
LinkList creatListTail(int n)
{
int i;
int e;
LinkList L,r,p;
//創建頭結點
L = (LinkList)malloc(sizeof(LNode));
r = L;
for(i=1;i<=n;i++)
{
p = (LinkList)malloc(sizeof(LNode));
scanf("%d",&e);
p->data = e;
r->next = p;
r = p;
}
r->next=NULL;
return L;
}
1.2單鏈表的刪除
單鏈表的刪除命令可以通過修改一個指針來實現,如圖所示:
代碼如下:
//刪除鏈表第n個元素。
int deleteList(LinkList L,int n)
{
if(L->next==NULL)
return 0;
LinkList p,q;
p = L;
for(int i=1;i<n;i++)
{
L = L->next;
p = L;
}
if(!(p->next))
return 0;
q = p->next;
p->next = q->next;
free(q);
return 0;
}
1.3單鏈表的插入
單鏈表的插入需要使用malloc調用從系統得到一個新單元並在之後執行兩次指針調整,如圖所示:
代碼如下
//假設插入到第n個結點的前面,插入的元素爲e
void insertList(LinkList L,int n,int e)
{
if(n<=0)
return ;
LinkList p,s;
s = (LinkList)malloc(sizeof(LNode));
s->data = e;
p = L;
for(int i=1;i<n;i++)
{
L = L->next;
p = L;
}
if(!(p->next))
return;
s->next = p->next;
p->next = s;
return ;
}
2循環鏈表
表中最後一個結點的指針指向頭結點,整個鏈表形成一個環。
循環鏈表的操作和線性鏈表基本一致,差別僅在於算法中的循環條件。(不是P爲空或者p->next爲空,而是他們是否等於頭指針)
2雙向鏈表
在雙向鏈表中結點有兩個指針域,一個指向直接後繼,另一個指向直接前驅
雙向鏈表的描述可以如下:
typedef struct DuLNode
{
ElemType data;
struct DuLnode *prior;
struct DuLnode *next;
}DuLnode,*DuLinkList;
和單鏈表類似,雙向鏈表也有循環表,如圖所示: