1,定義一個單鏈表
基礎定義先了解一下:
struct LNode{ //定義單鏈表結點類型
ElemType data; //每個節點存放一個數據元素
struct LNode *next; //指針指向下一個節點
}LNode,*LinkList;
/*
struct LNode *p=(struct LNode*)malloc(sizeof(struct LNode)); //增加一個新的結點,在內存中申請一個結點所需的空間,並用指針p 指向這個結點
*/
LNode *GetElem(LinkList L,int i){
int j=1;
LNode *p=L->next;
if(i==0)
return L;
if(i<1)
return NULL;
while(p!=NULL&&j<i){
p=p->next;
j++;
}
return p;
}
上述代碼*LNode GetElem(LinkList L,int i) 中需要注意的是:若強調這是一個單鏈表,使用 LinkList;若強調這是一個結點,則使用LNode * 。
1,不帶頭結點的單鏈表
struct LNode{ //定義單鏈表結點類型
ElemType data; //每個節點存放一個數據元素
struct LNode *next; //指針指向下一個節點
}LNode,*LinkList;
bool InitList(LinkList &L){ //初始化一個單鏈表
L=NULL; //空表,防止臟數據
return true;
}
void test(){
LinkList L; //聲明一個指向單鏈表的指針
//初始化一個空表
InitList(L);
//.....
}
2,帶頭結點的單鏈表
struct LNode{ //定義單鏈表結點類型
ElemType data; //每個節點存放一個數據元素
struct LNode *next; //指針指向下一個節點
}LNode,*LinkList;
//初始化一個單鏈表
bool InitList(LinkList &L){
L=(LNode *)malloc(sizeof(LNode)); //分配一個頭結點
if(L==NULL) //內存不足,分配失敗
return false;
L->next=NULL; //頭結點之后暫時還沒有結點
return true;
}
//判斷單鏈表是否為空(帶頭結點)
bool Empty(LinkList L){
if(L-next==NULL)
return true;
else
return false;
}
void test(){
LinkList L; //聲明一個指向單鏈表的指針
//初始化一個空表
InitList(L);
//.....
2,單鏈表的基本操作
1,插入
1,按位序插入(ListInsert(&L,i,e))
在第i 個位置插入元素e (帶頭結點)
bool ListInsert(LinkList &L,int i,ElemType e){
if(i<1)
return false;
LNode *p; //指針p 指向當前掃描到的節點
int j=0; //當前p指向的是第幾個結點
p=L; //L指向頭結點,頭結點是第0 個結點(不存數據)
while(p!=NULL&&j<i-1){ //循環找到第i-1個結點
p=p->next;
j++;
}
if(p==NULL) //i 值不合法
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s; //將結點s 連到p 之后
return true; //插入成功
}
不帶頭結點的:(不存在 “第0個“ 結點)實現代碼如下:
bool ListInsert(LinkList &L,int i,ElemType e){
if(i<1)
return false;
if(i==1){ //插入第1個結點的操作與其他結點操作不同
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=L;
L=s; //頭指針指向新結點
return true;
}
LNode *p; //指針p指向當前掃描到的節點
int j=1; //當前p 指向的是第幾個結點
p=L; //p指向第1個結點(注意:不是頭結點)
while(p!=NULL&&j<i-1){ //循環找到第i-1個結點
p=p->next;
j++;
}
if(p==NULL) //i 值不合法
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
s->data=e;
s->next=p->next;
p->next=s; //將結點s 連到p 之后
return true; //插入成功
}
2,指定結點的后插操作(InsertNextNode(LNode *p,ElemType e)
在p 結點之后插入元素e :
bool InsertNextNode(LNode *p,ElemType e){
if(p==NULL)
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
if(s==NULL) //內存分配失敗
return false;
s->data=e; //用結點s保存數據元素e
s->next=p->next;
p->next=s;
}
3,指定結點的前插操作
在p 結點之前插入**元素e **:
bool InsertPrioNode(LNode *p,ElemType e){
if(p==NULL)
return false;
LNode *s=(LNode *)malloc(sizeof(LNode));
if(s==NULL) //內存分配失敗
return false;
s->next=p->next;
p->next=s; //新結點s 連接到p 之后
s->data=p->data; //將p 中元素復制到s 中
p->data=e; //p 中元素覆蓋為e
return true;
}
結合下圖在體會一下:

下面再看一下在p 結點之前插入**結點s **:
bool InsertPrioNode(LNode *p,ElemType e){
if(p==NULL||s==NULL)
return false;
s->next=p->next;
p->next=s; //s 連接到p 之后
ElemType temp=p->data; //交換數據域部分
p->data=s->data;
s->data=temp;
return true;
}
這招偷天換日結合下圖好好體會一下:

2,刪除
1,按位序刪除(帶頭結點)
刪除表L 中第i 個位置的元素,並用e 返回刪除元素的值。那具體怎么做呢?我們要找到第 i-1 個結點,將其指針指向第 i+1 個結點,並釋放第 i 個結點。示例代碼如下:
bool ListDelete(LinkList &L,int i,ElemType &e){
if(i<1)
return false;
LNode *p; //指針p 指向當前掃描到的結點
int j=0; //當前p 指向的是第幾個結點
p=L; //L 指向頭結點,即第0個結點,不存數據
while(p!=NULL&&j<i-1){ //循環找到第i-1個結點
p=p->next;
j++;
}
if(p==NULL) //i 值不合法
return false;
if(p->next==NULL) //說明第i-1個結點之后無其他結點
return false;
LNode *q=p->next; //令q 指向被刪除結點
e=q->data; //用e 返回元素的值
p->next=q->next; //將 *q 結點從鏈中“斷開”
free(q); //釋放結點的存儲空間
return true; //刪除成功
}
2,指定結點的刪除
以下是刪除指定結點p 的操作:
bool DeleteNode(LNode *p){
if(p==NULL)
return false;
LNode *q=p->next; //令q 指向 *p 的后繼結點
p->data=p->next->data; //和后繼結點交換數據域
p->next=q->next; //將 *q 結點從鏈中“斷開”
free(q); //釋放后繼結點的存儲空間
return true;
}
上面幾行代碼如果沒有不是很理解的話,可以結合下面的動態進一步理解:

好了,以上就是關於單鏈表的定義,插入和刪除的一些基本操作。我們不要怕慢,打牢基礎在慢慢加速哦~
