1、線性表的鏈式存儲結構:n個結點(結點存數據元素和後繼元素的指針),鏈接爲一個鏈表,即爲線性表(a1,a2,……,an)的鏈式存儲結構。
2、鏈式存儲結構的頭指針:①頭指針是鏈表的必要元素!!無論鏈表是否爲空,頭指針均不爲空。②頭指針有標識作用,通常用來標識鏈表名。③頭指針指向鏈表的第一個結點(頭結點或第一個結點)。
3、頭結點:①頭結點不是必須的。②頭結點是爲了第一個元素前的插入或刪除和後面元素一樣,而設立的。放在第一個結點之前。數據域一般無意義,不過也可以存放鏈表長度。
4線性表的順序存儲結構和鏈式存儲結構的對比:
5、鏈式存儲結構代碼(以單鏈表爲例)
/************************************************************************/
/* (2)線性鏈式存儲 */
/************************************************************************/
#include <stdio.h>
#include <time.h>
#include <iostream>
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MaxSize 30 //存儲空間初始分配量
typedef int Status;
typedef int ElemType;
extern Status visit(ElemType c);
/* 線性表的單鏈表存儲結構 */
typedef struct Node //①定義Node結點:數據域+後繼結點地址的指針域;
{
ElemType data;
struct Node *next;
}Node; //②typedef struct Node Node:Node可替換爲 struct Node
typedef struct Node *LinkList; //定義LinkList鏈表,LinkList 可替換爲 struct Node *
//初始化順序線性表
Status InitList(LinkList *L)
{
*L=(LinkList)malloc(sizeof(Node)); //產生頭結點,並使L指向此頭結點
if(!(*L)) //存儲分配失敗
return ERROR;
(*L)->next =NULL; //令頭結點的指針域爲空
return OK;
}
/* 初始條件:順序線性表L已經存在 */
/* 操作結果:若L爲空表,則返回TRUE,否則返回FALSE */
Status ListEmpty(LinkList L)
{
if (L->next == NULL)
return TRUE;
else
return FALSE;
}
/* 初始條件:順序線性表L已經存在 */
/* 操作結果:將L重置爲空表 */
Status ClearList(LinkList L)
{
LinkList p,q;
p=(*L).next; //p指向第一個節點
while(p) //若p不爲空,表示還沒到表尾,一直while循環
{
q=p->next;
free(p); //釋放每一個結點所佔的內存空間
p=q;
}
(*L).next = NULL; // 將頭結點指針域置爲空
return OK;
}
/* 初始條件:順序線性表L已經存在 */
/* 操作結果:返回L中數據元素的個數*/
int ListLength(LinkList L)
{
int k=0;
LinkList p=L->next; //p指向L表的第一個結點
while(p)
{
k++;
p=p->next;
}
return k;
}
/* 初始條件:順序線性表已經存在,且1<=i<=LineList(L) */
/* 操作結果:用e返回L中第i個數據元素的值 */
Status GetElem(LinkList L, int i,ElemType *e)
{
int j;
LinkList p; //聲明一個結點p
p=L->next; //p指向鏈表的第一個結點
j=1;
while(p && j<i)
{
p=p->next;
j++;
}
if (!p || j>i) //如果p爲空,或j>i,則第i個元素不存在
return ERROR;
*e = p->data; //否則,第i個數據存在,取出即可
return OK;
}
/* 初始條件:順序線性表L已經存在 */
/* 操作結果:返回L中第1個與e滿足關係的數據元素的位序*/
int LocateElem(LinkList L,ElemType e)
{
int i=0;
LinkList p=L->next;
while(p)
{
i++;
if (e==p->data)
return i;
else
p=p->next;
}
return 0;
}
/* 初始條件:順序線性表L已經存在 */
/* 操作結果:在L中第i個位置之前插入新的數據元素e,L的長度加1 */
Status ListInsert(LinkList *L,int i,ElemType e)
{
int j;
LinkList p,s;
p=*L;
j=1;
while(p && j<i)
{
j++;
p=p->next;
}
if (!p || j>i)
return ERROR; //第i個元素不存在
s = (LinkList) malloc(sizeof(Node)); //生成新結點
s->data =e;
s->next=p->next;
p->next =s;
return OK;
}
/* 初始條件:線性順序表L已經存在 */
/* 操作結果:刪除L的第i個位置的數據元素,並用e返回其值,L的長度減1*/
Status ListDelete(LinkList *L,int i,ElemType *e)
{
int j;
LinkList p,q;
p=*L;
j=1;
while(p->next && j<i)
{
j++;
p=p->next;
}
if (!(p->next) || j>i)
return ERROR;
q=p->next;
p->next=q->next;
*e=q->data;
free(q); //系統回收該結點,釋放內存
return OK;
}
/* 初始條件:順序線性表L已經存在 */
/* 操作結果:依次對L的每個元素輸出*/
Status ListTraverse(LinkList L)
{
LinkList p=L->next; //p指向第一個結點
while(p)
{
visit(p->data);
p=p->next;
}
printf("\n");
return OK;
}
/*隨機產生n個元素的值,建立帶表頭結點的單鏈線性表L(頭插法)*/
void CreateListHead(LinkList *L,int n)
{
LinkList p;
int i;
srand(time(0)); //srand:產生隨機數,初始化隨機數種子
*L=(LinkList) malloc(sizeof(Node)); //這句和下句,是生成一個新結點表示頭結點,指向NULL表示只有頭結點
(*L)->next=NULL; //先建立一個帶頭結點的單鏈表
for (i=0;i<n;i++)
{
p=(LinkList)malloc(sizeof(Node)); //生成新的結點
p->data=rand()%100+1;
p->next=(*L)->next; //令p->next=NULL,從表頭插入
(*L)->next = p; //插入到表頭
}
}
/* 尾插法 */
void CreateListTail(LinkList *L,int n)
{
LinkList p,r;
srand(time(0));
*L = (LinkList)malloc(sizeof(Node));
r=(*L);
for(int i=0;i<n;i++)
{
p=(LinkList)malloc(sizeof(Node));
p->data=rand()%100+1;
r->next=p;
r=p; //將當前新結點定義爲表最終端的結點
}
r->next=NULL;
}
int main()
{
LinkList L;
ElemType e;
Status i;
int j,k;
i=InitList(&L);
printf("初始化鏈表L後,ListLength(L)=%d\n",ListLength(L));
for (j=1;j<=5;j++)
{
i=ListInsert(&L,1,j);
}
printf("在表頭依次插入1~5之後:L.data=");
ListTraverse(L);
printf("ListLength(L)=%d\n",ListLength(L));
i=ListEmpty(L);
printf("L是否爲空:i=%d(1:是;0:否)",i);
printf("\n");
i=ClearList(L);
i=ListEmpty(L);
printf("ClearList之後,L是否爲空:i=%d(1:是;0:否)",i);
printf("\n");
for (j=1;j<=10;j++)
{
ListInsert(&L,j,j);
}
printf("在L的表尾依次插入1~10之後,L.data=");
ListTraverse(L);
printf("ListLength(L)=%d",ListLength(L));
GetElem(L,5,&e);
printf("第5個元素爲:%d\n",e);
for(j=3;j<=4;j++)
{
k=LocateElem(L,j);
if(k)
printf("第%d個元素值爲%d\n",k,j);
else
printf("沒有值爲%d的元素\n",j);
}
k=ListLength(L);
printf("k=ListLength(L)=%d\n",k);
for(j=k+1;j>=k;j--)
{
i=ListDelete(&L,j,&e); //刪除第j個數
if (i == ERROR)
printf("刪除第%d個數據失敗\n",j);
else
printf("要刪除的第%d個數據爲:%d",j,e);
}
printf("依次輸出L中的元素:");
ListTraverse(L);
j=5;
ListDelete(&L,j,&e);
printf("要刪除的第%d個數據爲%d",j,e);
printf("依次輸出L中的元素:");
ListTraverse(L);
i=ClearList(L);
printf("\n清空L後:ListLength(L)=%d\n",ListLength(L));
CreateListHead(&L,5);
printf("頭插法:");
ListTraverse(L);
i=ClearList(L);
printf("\n清空L後:ListLength(L)=%d\n",ListLength(L));
CreateListTail(&L,5);
printf("尾插法:");
ListTraverse(L);
getchar();
}