不帶頭結點的單鏈表(基於c語言)


本篇文章的代碼大多使用無頭結點的單鏈表

相關定義:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int DataType;
typedef struct Linklist{
    LDataType data;
    struct Linklist *next;
}Linklist,*pLinklist;

 

 相關函數的定義:

pLinklist BuyNewNode(LDataType data);  //創建一個數據域為data的新結點
void InitLinklist(pLinklist *pL);  //初始化單鏈表
void PushBackLinklist(pLinklist* pL,LDataType data);  //尾插
void PushFrontLinklist(pLinklist *pL,LDataType data);  //頭插
void PopBackLinklist(pLinklist *pL);  //尾刪
void PopFrontLinklist(pLinklist *pL);  //頭刪
void PrintLinklist(pLinklist pL);  //打印出鏈表
pLinklist FindLinklist(Linklist *pL,LDataType data);  //找到數據域為data的第一個結點
void InsertLinklist(pLinklist *pL,pLinklist p,LDataType data);  //指定位置插入
void RemoveLinklist(pLinklist *pL,LDataType data);  //刪除第一個數據為data的結點
void RemoveAllLinklist(pLinklist *pL,LDataType data);  //刪除數據為data的全部結點
int IsEmpty(pLinklist pL);  //判斷單鏈表是否為空
void DestoryLinklist(pLinklist *pL);  //刪除整個鏈表,釋放內存

 由上面可以看出,只要是涉及到頭指針發生改變的,我們在函數中都是傳入指向頭指針的指針。就像我們在swap函數中要交換a和b的值,我們是傳入地址,而現在我們要改變頭指針的值,也必須要傳入指向頭指針的一個指針來進行相關的操作。

此處借鑒了c語言函數傳遞參數的問題

 下面是對函數的展開,我會比較詳細的分析一下函數實現:

0.動態生成新結點

pLinklist BuyNewNode(LDataType data){
  pLinklist NewNode = (pLinklist)malloc(sizeof(Linklist));
  if(pLinklist == NULL){
    printf("空間開辟失敗");
    return NULL;
  }
  NewNode->data = data;
  NewNode->next = NULL;
  return NewNode;
}

 

1.初始化操作

void InitLinklist(pLinklist *pL){
  assert(pL != NULL);
  (*pL) = NULL;
}

 

 2.尾插一個數據為data的結點

void PushBackLinklist(pLinklist *pL,LDataType data){
  assert(pL != NULL);  //大多數中都有這個,是為了防止使用空指針,書中經常會說,千萬不要使用空指針,你應該有印象
  pLinklist NewNode = BuyNewNode(data);
  if(*pL == NULL){  //判斷這個是否為空鏈表
    *pL = NewNode;
    return ;
  }
  pLinklist cur = *pL;
  while(cur->next != NULL){  //其實這里也可以用cur != NULL,但是上面已經把把空鏈表大情況寫出來了,如果再這樣寫會重復,不會錯,但是復雜一點點
    cur = cur->next;
  }
  cur->next = NewNode;
}

 

 3.頭插一個數據為data的結點

void PushFrontLinklist(pLinklsit *pL,LDataType data){
  assert(pL != NULL);
  pLinklist NewNode = BuyNewNode(data);
  if(*pL == NULL){
    *pL = NewNode;
    return ;  
  }
  NewNode->next = *pL;
  *pL = NewNode;
}

 

 4.判斷無頭鏈表是否為空

int IsEmptyLinklist(pLinklist pL){
  //這里的pL是一個指向鏈表的指針,而不是一個指向鏈表指針的指針
  return (pL == NULL);
}

 

 5.尾刪

void PopBackLinklist(pLinklist *pL){
  assert(pL != NULL);
  if(IsEmptyLinklist(*pL)){
    //*pL是一個指向鏈表的指針
    printf("鏈表為空");
    return ;
  }
  //尾刪需要找到前面那一個結點
  pLinklist cur = *pL;
  pLinklist pre;
  if(cur->next == NULL){
    *pL = NULL;
    free(cur);
    cur = NULL;
    return ;
  }
  while(cur->next){
    pre = cur;
    cur = cur->next;
  }
  pre->next = NULL;
  free(cur);
  cur = NULL;
}

 

 6.頭刪

void PopFrontLinklist(pLinklist *pL){
  assert(pL != NULL);
  if(*pL == NULL){
    printf("鏈表為空");
    return ;
  }
  pLinklist p = *pL;
  *pL = p->next;
  free(p);
  p = NULL;
}

 

 7.找到第一個數據為data的結點

pLinklist FindLinklist(pLinklist *pL,LDataType data){
  assert(pL != NULL);
  plinklist cur = *pL;
  while(cur != NULL){
    if(cur->data == data){
      return cur;
    }
    cur = cur->next;
  }
  return NULL;
}

 

 8.在給出的結點之前插入一個數據為data的結點

void InsertLinklist(pLinklist *pL,pLinklist p,LDataType data){
  assert(pL != NULL);
  pLinklist NewNode = BuyNewNode(data);
  pLinklist cur = *pL;
  while(cur->next != p){
    cur = cur->next;
  }
  NewNode->next = cur->next;
  cur->next = NewNode;
}

 

 9.刪除第一個數據為data的結點

void RemoveLinklist(pLinklist *pL,LDataType data){
  assert(pL != NULL);
  pLinklist cur = FindLinklist(pL,data);
  if(cur == NULL){
    printf("沒找到");
    return ;
  }
  if(cur == *pL){
    //剛好在第一個結點
    *pL = cur->next;
    free(cur);
    cur = NULL;
    return ;
  }
  pLinklist p = *pL;
  while(p->next != cur){
    p = p->next;
  }
  p->next = cur->next;
  free(cur);
  cur = NULL;
}

 

 10.刪除每一個數據都是data的結點

void RemoveAllLinklist(pLinklist *pL,LDataType data){

  assert(pL != NULL); //刪除每一個數據域都是data的結點
  pLinklist cur = NULL;
  pLinklist p = *pL;  //pre保存要刪除結點的前一個結點
  pLinklist pre = *pL;
  while(p){
    if (p->data == data && (*pL) == p){
    //第一個結點是
    pre = p;
    p = p->next;
    *pL = p;
    free(pre);
    pre = NULL;
  }
  else if(p->data == data){
    //后續結點是
    cur = p;
    p = p->next;
    pre->next = p;
    free(cur);
    cur = NULL;
  }
  else{
    //此結點不是
    pre = p;
    p = p->next;
    }
  }

}

 

 11.打印出鏈表

void PrintLinklist(Linklist *pL){
    pLinklist cur = pL;    //打印鏈表 
    while(cur){
        printf("%d--->",cur->data);
        cur = cur->next;
    }
    printf("NULL\n");
} 

 

12.摧毀鏈表 

void DestoryLinklist(pLinklist *pL){
    assert(pL != NULL);    //摧毀鏈表 
    pLinklist cur = *pL;
    pLinklist pre = NULL;
    if (*pL == NULL){
        printf("鏈表為空");
        return ;
    }
    if (cur->next = NULL){
        *pL = NULL;
        free(cur);
        cur = NULL;
        return ;
    }
    while(cur){
        pre = cur;
        cur = cur->next;
        free(pre);
        pre = NULL;
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 添加到短語集
     
    • 沒有此單詞集:中文(簡體) -> 英語...
       
    • 創建新的單詞集...
  • 拷貝


免責聲明!

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



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