c 語言數據結構之單鏈表的插入和刪除操作


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;
}

結合下圖在體會一下:

image-20220217115342428

下面再看一下在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;
}

這招偷天換日結合下圖好好體會一下:

image-20220217115602453

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;
}

上面幾行代碼如果沒有不是很理解的話,可以結合下面的動態進一步理解:

GIF

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM