數據結構--鏈表(C語言版)

/*
  數據結構鏈表的生成,main函數部分
*/
#include <stdio.h>
#include <stdlib.h>
#include "Link_List.h"
/*
    數據的存儲方式:
            非線性--鏈表
*/

int main()
{
    int Length = 0;
    int TempValue = 0;
    int Value;

    PMyList PListHead = NULL;
    PListHead = CreatList();//生成頭指針

    printf("\n排序前:");
    TraveList(PListHead);//遍歷

    printf("\n排序後: ");
    SortList(PListHead);
    TraveList(PListHead);

    InseElement(PListHead, 3, 5);
    TraveList(PListHead);

    printf("\n請輸入您要刪除的值: ");
    scanf("%d", &Value);
    DeleElement(PListHead, Value, &TempValue);
    printf("\n要刪除的數據是: %d", TempValue);
    printf("\n刪除後的鏈表爲: ");
    TraveList(PListHead);

    Length = LenList(PListHead);
    printf("\n\n鏈表的長度爲:%d\n", Length);


    return 0;
}

/*

    鏈表的頭文件函數聲明部分

*/

#ifndef LINK_LIST_H_INCLUDED
#define LINK_LIST_H_INCLUDED
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

/*
typedef struct _myList   //新建一個鏈表的結構體
{
    char name[10];
    int score;
    struct _myList* pNext;//每一個節點用於尋找到下一個節點的指針
}* pMylist, MyList;
*/

 typedef struct _myList     //每一個節點都有一個數據域和指針域
{
    int date;               //數據域
    struct _mylist* pNext;  //指針域--每一個節點都有一個指向下一個節點的指針(下一個節點的地址)
}* PMyList, MyList;

PMyList CreatList();        //用於生成一個節點
void TraveList(PMyList);    //鏈表的遍歷
bool EmptyList(PMyList);    //判斷鏈表是否爲空
bool FullList(PMyList);     //判斷鏈表是否爲滿
int LenList(PMyList);       //求鏈表的長度
void SortList(PMyList);     //對鏈表進行排序
bool InseElement(PMyList, int, int);    //在鏈表中插入數據,先輸入頭指針(PMyList),找到鏈表,在鏈表那個位置的前面(int)插入什麼數字(int)
bool DeleElement(PMyList, int, int *);  //從鏈表中刪除數據,並把刪除的數據返回

#endif // LINK_LIST_H_INCLUDED

/*

    實現文件部分

*/

#include <stdio.h>
#include <stdlib.h>
#include "Link_List.h"

PMyList CreatList(void)//節點的生成
{
    int i, val; //臨時存放節點的值
    int Len;    //節點數

    PMyList PListHead = (PMyList)malloc(sizeof(MyList));//動態生成頭結點的指針變量
    if(NULL == PListHead)
    {
        printf("\n PListHead 動態分配內存失敗!");
        exit(-1);
    }

    PMyList PTail = PListHead;//生成一個尾節點,這個節點一直指向鏈表最後一個元素的指針域中
    PTail->pNext = NULL;

    printf("\n節點總數:");
    scanf("%d", &Len);

    while(Len < 0)
    {
        printf("\n節點數必須是非負數,請重新輸入:");
        scanf("%d", &Len);
        fflush(stdin);
    }

    //1.用循環的方式來生成鏈表
    for(i = 0; i < Len; i++)
    {
        printf("\n請輸入第%d個節點的值:", i + 1);
        scanf("%d", &val);

        PMyList PNew = (PMyList)malloc(sizeof(MyList)); //用動態分配內存的方式,生成了一個節點
        if(NULL == PNew)
            {
                printf("\n PNew 動態分配內存失敗!");
                exit(-1);
            }
        PNew->date = val;    //爲生成的新節點的數據域進行賦值
        PTail->pNext = PNew; //保證了PTail始終是指向最後一個節點的指針
        PNew->pNext = NULL;  //是最後一個節點的指針域爲空
        PTail = PNew;        //連同數據域一同賦值給PTail
    }

    return PListHead;
}

void TraveList(PMyList PListHead)//通過鏈表的頭地址來進行鏈表的遍歷
{
    PMyList PTem = PListHead->pNext;//定義一個結構體指針,這個指針指向頭結點指向的下一個節點,如果這個節點的指針域爲空,則遍歷結束
    printf("\n遍歷鏈表: ");
    while(NULL != PTem)
    {
        printf("%d\t", PTem->date);
        PTem = PTem->pNext;
    }

    return;
}

bool EmptyList(PMyList PListHead)//判斷鏈表是否爲空
{
    if(NULL == PListHead->pNext )
    {
        return true;
    }
    return false;
}

bool FullList(PMyList PListHead)//判斷鏈表是否爲滿
{
    return false;
}

int LenList(PMyList PListHead)
{
    PMyList PTem = PListHead->pNext;//定義一個臨時的PMylist型的指針變量,並將這個指針指向第一個節點
    int Length = 0;
    while(NULL != PTem)
    {
        Length++;
        PTem = PTem->pNext;//如果不爲空,將PTem下一個節點的地址賦給PTem
    }
    return Length;
}


void SortList(PMyList PListHead)//對鏈表中的數據進行排序
{
    int len = LenList(PListHead);//獲取鏈表的長度
    int i, j, temp;
    PMyList PTemp1, PTemp2, PTemp3;
    if(EmptyList(PListHead))
        printf("鏈表爲空,不予以排序!");
    else
    {
        for(i = 0, PTemp1 = PListHead->pNext; i < len - 1; i++, PTemp1 = PTemp1->pNext)            //i = 0 ; i < len - 1; i++
        {
            for(j = 0, PTemp2 = PListHead->pNext; j < len - i - 1; j++, PTemp2 = PTemp2->pNext)    //j = 0; j < len - i - 1; j++
            {
                PTemp3 = PTemp2->pNext;
                if(PTemp2->date > PTemp3->date)    //a[j] > a[j+1]
                {
                    temp = PTemp2->date;
                    PTemp2->date = PTemp3->date;
                    PTemp3->date = temp;
                }
            }
        }
    }

    return;
}

/*

假設鏈表的長度爲3,要求插入的元素位置爲2,值爲22

    1.先判斷這個鏈表是否爲空,並且插入的元素位置是否是大於等於1 (>= 1), 最小值爲1
      循環的作用是求出位置爲1的節點的指針域,這個指針域指向第二個節點
    2.if語句用於判斷,插入的位置是否大於等於1或者鏈表是否爲空,如果爲空,返回false
    3.PNew->date = Content;
      動態構造一個新節點,新節點的值域爲所要插入的值
      PMyList PTem2 = PTem->pNext;
      再次構造一個臨時節點,這個節點的值爲第一個節點的指針域,即指向第二個節點
      PTem->pNext = PNew;
      將第一個節點的指針域指向新創建的變量
      PNew->pNext = PTem2;
      新創建的變量的指針域指向爲原來鏈表的第二個節點

bool InseElement(PMyList PListHead, int Place, int Content)//在鏈表PListHead中的第Place位置前插入Content
{
    int i = 0;
    PMyList PTem = PListHead; //定義一個指針,這個指針的指向和頭指針一樣

    while(NULL != PTem && i < Place - 1)//如果這個鏈表不爲空,並且插入的位置最多大於鏈表長度(最大值+1)
    {
        PTem = PTem->pNext;
        i++;
    }

    if(i > Place - 1 || NULL == PTem){
        return false;
    }

    PMyList PNew = (PMyList)malloc(sizeof(MyList));
    if(NULL == PNew)
    {
        printf("\n InseElement 中 PNew 內存分配失敗!\n");
        exit(-1);
    }
    else
    {
        PNew->date = Content;
        PMyList PTem2 = PTem->pNext;
        PTem->pNext = PNew;
        PNew->pNext = PTem2;

        return true;
    }
}
*/

bool DeleElement(PMyList PListHead, int Content, int * TemValu)
{
    int Length = 0;
    PMyList PTem1 = PListHead;
    PMyList PTem2 = NULL;

    if(EmptyList(PListHead))
    {
        printf("鏈表爲空,無法刪除!");
        return false;
    }
    else
    {
        while(NULL != PTem1->pNext)//如果第一個節點不爲空
        {
            PTem2 = PTem1->pNext;//要刪除節點的前一個節點
            if(Content == PTem2->date)
            {
                (*TemValu) = PTem2->date;
                PTem1->pNext = PTem2->pNext;//將刪除節點的前一個節點指向要刪除節點的後一個節點
                PTem2->pNext = NULL;//將要刪除的節點的指針域置爲空
                free(PTem2);
                return true;
            }

            PTem1 = PTem1->pNext;
            Length++;
        }

        if(LenList(PListHead) == Length){
            printf("鏈表中沒有這個數字!");
            return false;
        }
        return true;
    }
}

bool InseElement(PMyList PListHead, int Place, int Content)//(By Myslef)增加節點
{
    PMyList PTem1 = PListHead;   //頭指針
    PMyList PTem2 = PListHead->pNext;//第一個節點

    int i, len, Lenth = LenList(PListHead);//獲取鏈表的長度
    if(EmptyList(PListHead) || Place <= 0 || Place > Lenth + 1)//如果要刪除的節點位置,小於零,或者大於節點 Length+1刪除失敗
    {
        return false;
    }
    else
    {
        for(i = 0; i < Place - 1; i++)//移動節點,使 PTem2 爲 Place 位置的節點,PTem2爲 place-1 位置的節點
        {
            PTem1 = PTem1->pNext;
            PTem2 = PTem2->pNext;
        }

        PMyList PNew = (PMyList)malloc(sizeof(MyList));//創建一個新的節點
        if(NULL == PNew)
        {
        printf("\n InseElement 中 PNew 內存分配失敗!\n");
        exit(-1);
        }
        PNew->date = Content;
        PTem1->pNext = PNew;
        PNew->pNext = PTem2;

        return true;
    }
}
















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章