数据结构--链表(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;
    }
}
















猜你喜欢

转载自blog.csdn.net/qq_41637987/article/details/81052692
今日推荐