線性表——單鏈表的概念
阿新 • • 發佈:2018-11-13
線性表---單鏈表
typedef struct node {
ElemType data; //資料域
struct node *next; //指標域
}LNode, *LinkList; // LinkList為指向LNode型別的指標
結點:資料元素的儲存映像
連結串列:n個結點連結成起來形成一個連結串列,即為線性表的 鏈式儲存結構
單鏈表: 結點中只包含一個指標域
-
頭指標:指向連結串列中第一個結點(或為頭結點、或為首元結點)的指標
-
頭結點:在連結串列的首元結點之前附設的一個結點;資料域內只放表長等資訊,它不計入表
長度。其作用是統一空表、和非空連結串列的形式 -
首元結點:指連結串列中儲存線性表第一個資料元素a1的結點
線性表的鏈式表示和實現
(1)單鏈表的建立
- 先開闢頭指標,建立頭結點;
- 為每個新元素開闢儲存空間,並賦值
- 將新結點連結到表尾
1、尾插法
/*例1:用尾插法建立26個字母的帶表頭結點的單鏈表*/ /*演算法1-1*/ LinkList createLinkList1() //尾插法建立帶表頭結點的單鏈表 { LNode *L,*p,*s; //L頭指標, p指向尾結點, s指向新結點 L=(LNode *) malloc(sizeof(LNode)); //申請空白結點, L指向頭結點 L->next =NULL; //建立了頭結點 p=L; //p指向當前的尾結點 for(i=1;i<=26;i++) { s=(LNode *) malloc(sizeof(LNode)); //申請空白結點, s指向 s->data=i+‘a’-1; //給s->data 賦值 p->next=s; s->next =NULL; //s指向的結點插入單鏈表的表尾 p=s; //p總是指向當前連結串列的尾結點 , 等價於p=p->next } return L; } /*演算法1-2*/ void createLinkList2(LinkList *L) { //尾插法建立帶表頭結點的單鏈表 ,L指向頭結點的指標的指標 Lnode *p,*s; //p指向尾結點, s指向新結點 *L=(LNode *) malloc(sizeof(LNode)); //申請空白結點, *L指向頭結點 if (*L==NULL) exit(0); *L->next =NULL; //建立了頭結點 p=*L; //p指向當前的尾結點 for(i=1;i<=26;i++) { s=(LNode *) malloc(sizeof(LNode)); //申請空白結點, s指向 if (!s) exit(0); s->data=i+‘a’-1; //給s->data 賦值 p->next=s; s->next =NULL; //s指向的結點插入單鏈表的表尾 p=s; //p總是指向當前連結串列的尾結點 , 等價於p=p->next } }
2、頭插法
/*例2:用頭插法建立26個字母的帶表頭結點的單鏈表*/ /*演算法2-1*/ LinkList createLinkList1() /頭插法建立帶表頭結點的單鏈表 { LNode *L,*s; //L頭指標, s指向新結點 L=(LNode *) malloc(sizeof(LNode)); //申請空白結點, L指向頭結點 L->next =NULL; //建立了頭結點 for(i=26;i>=1;i--) { s=(LNode *) malloc(sizeof(LNode)); //申請空白結點, s指向 s->data=i+‘a’-1; //給s->data 賦值 s->next=L->next; L->next =s; //s指向的結點插入頭結點後面 } return L; } /*演算法2-2*/ void createLinkList2(LinkList *L) { //L指向頭結點的指標的指標 LNode *s; //p指向尾結點, s指向新結點 *L=(LNode *) malloc(sizeof(LNode)); //申請空白結點, *L指向頭結點 if (*L==NULL) exit(0); *L->next =NULL; //建立了頭結點 for(i=26;i>=1;i--) { s=(LNode *) malloc(sizeof(LNode)); //申請空白結點, s指向 if (!s) exit(0); s->data=i+‘a’-1; //給s->data 賦值 s->next=*L->next; *L->next =s; //s指向的結點插入頭結點的後面 } }
(2)單鏈表的查詢
思路:從頭指標開始逐一查詢
/*例3:單鏈表的查詢*/
LNode* GetElem_L2(LinkList L, ElemType x)
{
//在帶頭結點的單鏈表L中 查詢元素值為x的結點,
//若找到返回指向該結點的指標,否則返回NULL.
LNode *p;
p=L->next; //p指向首元結點
while (p->data!=x && p)
{
p=p->next; //p指標後移
}
return p;
}
演算法的時間複雜度:O(n)
(3)單鏈表的插入
在單鏈表中第i個位置插入一個元素x的示意圖如下:
/*例4:單鏈表的插入*/
bool ListInsert_L(LinkList *L, int i, ElemType e)
{
// L 為指向帶頭結點的單鏈表的頭指標的指標
//在連結串列中第i 個結點之前插入新的元素 e
LNode *p; int j;
p = *L; j = 0;
while (p && j < i-1)
{
p = p->next; ++j;
} // 尋找第 i-1 個結點
if (!p || j > i-1)
{
return false; // i 大於n+1或者小於1
}
s = (LinkList) malloc(sizeof(LNode)) ; // 生成新結點
if ( s == NULL)
{
return false;
}
s->data = e;
s->next = p->next; p->next = s; // 插入
return true;
} // LinstInsert_L
演算法的時間複雜度:O(n)
(4)單鏈表的刪除
/* 刪除單鏈表 */
void deleteList(LNode *pHead)
{
LNode *p1,*p2;
p1 = pHead;//p1指向第一個結點
while(p1->next != pHead)//當p1不指向頭結點時
{
p2 = p1->next;
free(p1);//刪除第n個連結串列
p1 = p2;
}
free(pHead);//刪除頭結點
}
演算法時間複雜度:O(n)