C語言實現單鏈表__C語言

來源:互聯網
上載者:User

1、用於存放聲明的標頭檔

#define _CRT_SECURE_NO_WARNINGS#pragma once#include <stdio.h>#include <assert.h>#include <malloc.h>typedef int DataType;typedef struct SListNode{    DataType data;                    //鏈表中存放的資料    struct SListNode *pNextNode;      //指向下一節點的指標}SListNode, *PSListNode;// 初始化單鏈表(對於無頭結點單鏈表,該函數沒有意義)void InitList(PSListNode* pHead);// 銷毀單鏈表void DestroyList(PSListNode* pHead);// 尾插void PushBack(PSListNode* pHead, DataType data);// 尾出void PopBack(PSListNode* pHead);// 頭插void PushFront(PSListNode* pHead, DataType data);// 頭出void PopFront(PSListNode* pHead);// 在鏈表中尋找元素dataPSListNode Find(PSListNode pHead, DataType data);// 刪除pos位置的結點(注意不能用那種替換形式)void  Erase(PSListNode* pHead, PSListNode pos);// 在鏈表的pos位置插入元素datavoid  Insert(PSListNode* pHead, PSListNode pos, DataType data);//列印鏈表存放的資料void PrintList(PSListNode pHead);

2、用於實現聲明的.c檔案

#include "SListNode.h"//這兒的參數是二級指標,因為要對結構體指標的內容進行修改,所以必須傳該指標的地址(即一個二級指標)//傳一級指標的話相當於是值傳遞,不會對實參有改變void InitList(PSListNode* pHead){    assert(pHead);    *pHead = NULL;}PSListNode ByeNode(DataType data){    PSListNode pNewNode = (PSListNode)malloc(sizeof(struct SListNode));    if (NULL != pNewNode)    {        pNewNode->data = data;        //注意使開闢的新節點的指向為空白        pNewNode->pNextNode = NULL;    }    return pNewNode;}void PushBack(PSListNode* pHead, DataType data){    PSListNode pNode = NULL;    PSListNode pNewNode = NULL;    assert(pHead);    if (NULL == (*pHead))    {        //此時可以不對ByeNode函數是否成功開闢空間做檢測,因為即使它沒有開闢成功空間,        //那麼使頭結點頭結點等於NULL邏輯一樣正確        *pHead = ByeNode(data);    }    else    {        pNode = *pHead;        //找到尾節點        while (NULL != pNode->pNextNode)        {            //儲存尾節點            pNode = pNode->pNextNode;        }        pNewNode = ByeNode(data);        //當開闢空間失敗,說明向鏈表裡插入了一個null 指標        pNode->pNextNode = pNewNode;    }}void PopBack(PSListNode* pHead){    PSListNode pPerNode = NULL;    PSListNode pCurNode = NULL;    assert(pHead);    if (NULL == (*pHead))    {        printf("鏈表中沒有資料節點。\n");    }    else    {        pCurNode = *pHead;        //注意迴圈結束的條件        while (NULL != pCurNode->pNextNode)        {            pPerNode = pCurNode;            pCurNode = pCurNode->pNextNode;        }        //把要刪除的結點從鏈表中斷開(讓該節點的上一個結點指向該結點的下一個結點)        pPerNode->pNextNode = NULL;        //刪除該結點        free(pCurNode);        pCurNode = NULL;    }}void PushFront(PSListNode* pHead, DataType data){    assert(pHead);    if (NULL == (*pHead))    {        //此時可以不對ByeNode函數是否成功開闢空間做檢測,因為即使它沒有開闢成功空間,        //那麼使頭結點頭結點等於NULL邏輯一樣正確        *pHead = ByeNode(data);    }    else    {        PSListNode pNewNode = ByeNode(data);        if (NULL == pNewNode)        {            printf("開闢節點空間失敗。\n");        }        else        {            //使指向頭結點的指標指向新開闢的節點,新開闢的節點指向鏈表中原來的頭結點            pNewNode->pNextNode = *pHead;            *pHead = pNewNode;        }    }}void PopFront(PSListNode* pHead){    assert(pHead);    if (NULL == (*pHead))    {        printf("鏈表中沒有資料節點。\n");    }    else    {        PSListNode pNode = *pHead;        //直接使頭結點指向鏈表中第三個節點,即可做到頭刪的目的        *pHead = (*pHead)->pNextNode;        free(pNode);        pNode = NULL;    }}PSListNode Find(PSListNode pHead, DataType data){    PSListNode pNode = pHead;    while (NULL != pNode)    {        if (pNode->data == data)        {            return pNode;        }        else        {            pNode = pNode->pNextNode;        }    }    //沒有找到對應的結點    return NULL;}void  Erase(PSListNode* pHead, PSListNode pos){    //更簡單的方法(pos指向的結點在鏈表中):    //直接交換pos指向的節點和pos指向的節點的下一個結點的資料,然後使pos指向的節點的下一個結點為它的下下一個結點    PSListNode pCurNode = *pHead;    PSListNode pPerNode = *pHead;    assert(pHead);    if (NULL == pos)    {        return;    }    //要是傳的參數沒有在鏈表中,那麼刪除就顯得沒有意義了,因此對pos的檢測(pos是否是鏈表中的某個節點)可有可無    while ((pCurNode != pos) && (pCurNode != NULL))    {        pPerNode = pCurNode;        pCurNode = pCurNode->pNextNode;    }    //使當前結點的上一個結點指向當前結點的下一個結點,然後釋放當前結點的空間,即可做到刪除當前結點    pPerNode->pNextNode = pPerNode->pNextNode->pNextNode;    free(pCurNode);    pCurNode = NULL;}void  Insert(PSListNode* pHead, PSListNode pos, DataType data){    //更簡單的方法(pos指向的結點在鏈表中):    //直接交換pos指向的節點和新插入的節點的的資料,然後使新插入的結點的下一個結點為pos指向的節點的下一個結點,    //pos指向的節點的下一個結點為新插入的結點    PSListNode pTempNode = *pHead;    PSListNode pNode = *pHead;    assert(pHead);    //pTempNode!=NULL是為了避免pos是一個建立的孤結點,它沒有插入到鏈表中    while ((pTempNode != pos) && (pTempNode != NULL))    {        pNode = pTempNode;        pTempNode = pTempNode->pNextNode;    }    if ((pTempNode == NULL) && (pos != NULL))    {        printf("鏈表中不存在該結點!\n");        return;    }    else    {        PSListNode pNewNode = ByeNode(data);        if (NULL == pNewNode)        {            printf("開闢空間失敗。\n");        }        else        {            pNewNode->pNextNode = pNode->pNextNode;            pNode->pNextNode = pNewNode;        }    }}void PrintList(PSListNode pHead){    PSListNode pNode = pHead;    //當pHead指向空時,說明此時鏈表中沒有資料,那麼不會進入列印資料的迴圈,而是等到函數結束返回    while (NULL != pNode)    {        printf("%d  ", pNode->data);        pNode = pNode->pNextNode;    }    printf("\n");}void DestroyList(PSListNode* pHead){    PSListNode pCurNode = NULL;    PSListNode pPerNode = *pHead;    assert(pHead);    while (NULL != pCurNode)    {        //每次銷毀鏈表最前面那個結點的空間        pPerNode = pCurNode->pNextNode;        free(pCurNode);        //不會出現野指標        pCurNode = pPerNode;    }}

3、用於測試函數正確性的Test.c檔案

#include "SListNode.h"//Test PushBack() / PopBack()void TestFun1(){    PSListNode pHead = NULL;    InitList(&pHead);    PushBack(&pHead, 0);    PushBack(&pHead, 1);    PushBack(&pHead, 2);    PushBack(&pHead, 3);    PrintList(pHead);    PopBack(&pHead);    PopBack(&pHead);    PrintList(pHead);}//Test PushFront() / PopFront()void TestFun2(){    PSListNode pHead = NULL;    InitList(&pHead);    PushFront(&pHead, 0);    PushFront(&pHead, 1);    PushFront(&pHead, 2);    PushFront(&pHead, 3);    PrintList(pHead);    PopFront(&pHead);    PopFront(&pHead);    PrintList(pHead);}//Test Find() / Erase() / Insert()void TestFun3(){    PSListNode pHead = NULL;    PSListNode pRetNode = NULL;    InitList(&pHead);    PushBack(&pHead, 0);    PushBack(&pHead, 1);    PushBack(&pHead, 2);    PushBack(&pHead, 3);    PrintList(pHead);    pRetNode = Find(pHead, 2);    printf("%d\n", pRetNode->data);    Erase(&pHead, Find(pHead, 1));    PrintList(pHead);    Insert(&pHead, Find(pHead, 2), 1);    PrintList(pHead);}//Test DestroyList()void TestFun4(){    PSListNode pHead = NULL;    InitList(&pHead);    PushBack(&pHead, 0);    PushBack(&pHead, 1);    PushBack(&pHead, 2);    PushBack(&pHead, 3);    DestroyList(&pHead);    PrintList(pHead);}int main(){    //TestFun1();    //TestFun2();    //TestFun3();    TestFun4();    system("pause");    return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.