/*
数据结构链表的生成,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;
}
}