1. 程式人生 > >資料結構——單鏈表實現

資料結構——單鏈表實現

鏈式儲存特點

在鏈式儲存中,節點之間的儲存單元地址可能是不連續的。鏈式儲存中每個結點都包含兩部分:儲存元素本身的資料域和儲存結點地址的指標域。結點中的指標指向的是下一個結點,也就是儲存的下一個結點的地址。

鏈式儲存的實現

1.建立連結串列

在建立連結串列時,頭結點不儲存資料,但可以儲存連結串列的資訊。

struct Header
{
    int length;//記錄連結串列大小
    struct Node *next; //指向第一個結點的指標
};

儲存資料的結點包含兩部分內容:資料域和指標域。

struct Node
{
    int data;
//資料域 struct Node *next; //指向下一個結點的指標 };

為了方便定義,將兩個struct 用typedef重新定義:

typedef struct Node List; //節點
typedef struct Header pHead; //頭節點

建立連結串列時,只需要建立一個頭結點,每儲存一個元素就分配一個儲存單元,然後將儲存單元的地址儲存在上一個結點:

pHead* creatList()
{
    pHead* ph=(pHead *)malloc(sizeof(pHead)); //為頭結點分配記憶體
    ph->length=0; //為頭結點初始化,此時連結串列長度為0
ph->next=NULL; return ph; //將頭結點地址返回 }

2.獲取連結串列大小

//獲取連結串列的大小
int Size(pHead* ph)
{
    if(ph==NULL)
    {
        printf("傳入引數有誤!");
    }
    return ph->length;
}

3.插入元素

在連結串列中插入元素時要比在順序表中快。比如在pos位置插入,則先斷開pos-1與pos的連結,然後將pos-1結點的指標指向val結點,將val結點的指標指向pos。

//插入元素,在pos位置插入元素val
void Insert(pHead* ph,int pos,int val) { if(ph==NULL || pos<0 || pos>ph->length) { printf("傳入引數有誤!"); return; } //首先將值val儲存在一個結點中 List *pval=(List *)malloc(sizeof(List)); pval->data=val; List *pCur=ph->next; if(pos==0) //插在首節點 { ph->next=pval; pval->next=pCur; } else { for(int i=1;i<pos;i++) { pCur=pCur->next; } pval->next=pCur->next; pCur->next=pval; } ph->length++; //長度加1 return; }

4.查詢某個元素

查詢連結串列中的某個元素,其效率沒有順序表高,因為不管查詢的元素在哪個位置,都需要將它前面的元素都全部遍歷才能找到它。

//查詢某個元素,並返回它的結點
List* find(pHead* ph,int val)
{
    if(ph==NULL)
    {
        printf("輸入引數有誤");
        return NULL;
    }
    //遍歷連結串列來查詢元素
    List* pTmp=ph->next;
    do
    {
        if(pTmp->data==val)
        {
            return pTmp;
        }
        pTmp=pTmp->next;
    }while(pTmp->next!=NULL);
    printf("沒有值為%d的元素\n",val);
    return NULL;
}

5.刪除元素

在刪除元素時,首先將被刪除元素與上下結點之間的連結斷開,然後將這兩個上下結點重新連結。

//刪除節點,刪除值為val的元素,刪除成功,返回刪除的元素
void Delete(pHead * ph,int val)
{
    if(ph==NULL)
    {
        printf("傳入引數有誤");
        return;
    }
    List* pval=find(ph,val);
    if(pval==NULL)
    {
        printf("沒有找到值為%d的元素\n",val);
        free(pval); //釋放結點
        return;
    }

    List* pRe=ph->next;
    List* pCur=NULL;
    if(pRe->data==val) //如果刪除的是第一個節點
    {
        ph->next=pRe->next;
        ph->length--;
        free(pRe); //釋放結點
        return;
    }
    else
    {
        for(int i=0;i<ph->length;i++)
        {
            pCur=pRe->next;
            if(pCur->data==val)
            {
                pRe->next=pCur->next;
                ph->length--;
                return;
            }
            pRe=pRe->next;
        }
        free(pCur); //釋放結點
    }
    return;
}

6.銷燬連結串列

銷燬連結串列時,將連結串列中每個元素結點釋放,頭結點可以釋放,也可以保留,將其置為初始化狀態。

//銷燬連結串列
void Destroy(pHead *ph)
{
    List* pCur=ph->next;
    List* pTmp;
    if(pCur==NULL)
    {
        printf("傳入引數有誤");
    }
    while(pCur->next!=NULL)
    {
        pTmp=pCur->next;
        free(pCur); //將結點釋放
        pCur=pTmp;
    }
    ph->length=0; //初始化頭結點
    ph->next=NULL; 
    printf("連結串列已銷燬!\n");
}

7.遍歷列印連結串列

//遍歷列印連結串列
void print(pHead * ph)
{
    List * pTmp=ph->next;
    if(ph==NULL)
    {
        printf("傳入引數有誤");
    }
    while(pTmp!=NULL)
    {
        printf("%d ",pTmp->data);
        pTmp=pTmp->next;
    }
    printf("\n");
}

8.樣例測試

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

//所有函式宣告
pHead* creatList(); //建立連結串列
int Size(pHead* ); //獲取連結串列的大小
void Insert(pHead*,int,int); //插入元素
List* find(pHead*,int); //查詢某個元素
void Delete(pHead*,int); //刪除節點
void Destroy(pHead*); //銷燬連結串列
void print(pHead*); //遍歷列印連結串列

int main()
{
    List * ret;
    pHead * ph=creatList();
    int arr[10]={1,2,3,4,5,6,7,8,9,0};
    for(int i=0;i<10;i++)
    {
        Insert(ph,0,arr[i]);
    }

    printf("連結串列長度:%d\n",Size(ph));
    print(ph);
    printf("刪除連結串列中的節點\n");
    int num;
    scanf("%d",&num);
    Delete(ph,num);
    printf("元素刪除成功,刪除元素%d後,連結串列中元素為:\n",num);
    print(ph);

    ret=find(ph,3);
    if(ret)
    {
        printf("get!\n");
    }
    else
    {
        printf("No!\n");
    }
    Destroy(ph); 
    return 0;
}

結果:

連結串列長度:10
0 9 8 7 6 5 4 3 2 1
刪除連結串列中的節點
2
元素刪除成功,刪除元素2後,連結串列中元素為:
0 9 8 7 6 5 4 3 1
get!
連結串列已銷燬!