数据结构是数据对象以及其中的相互关系和构造方法。在数据结构中,有一种线性存储结构为线性表。链表属于线性表的链式存储结构。
一、链表概述
存在原因:之前使用数组存放数据,但使用数组时要指定数组中包含元素的个数,如果该数组中加入的元素超过数组大小,则不能将内容保存,若定义一个超大的数组,这样又浪费空间。
链表这种存储方式可以解决上述问题,让其存储个数不受限定,添加元素时,存储的个数就会随之改变。
在链表中有一个头指针——head,在该指针变量中保存一个地址,从图中可以看到该地址为一个变量的地址,即头指针指向一个元素,链表中的每一个元素包括2部分,数据部分和指针部分,最后一个元素的指针指向NULL,表示指向的地址为空。
struct Student
{
char name[10];
int number;
struct Student* pNext; //指针部分
};
- 添加节点?
当有新的节点要添加到链表中时,原来最后一个节点的指针将保存新添加的节点地址,而新节点的指针指向空(NULL),当添加完成后,新节点将成为链表中的最后一个节点。从添加节点的过程中就可以看出,不用担心链表的长度会不会超出范围的问题。
二、创建动态链表
从上述看,链表并不是一开始就设置好自身大小。而是根据节点的多少来决定大小,得出:链表的创建过程是一个动态的创建过程。
动态创建一个节点时,要其分配内存
动态创建会用到函数:
- malloc(): 在内存中动态地分配一块size大小的内存空间,malloc 函数会返回一个指针,该指针指向分配地内存空间,如果出现错误,返回NULL。
- calloc():在内存中动态分配n个长度为size的连续内存空间数组,calloc函数会返回一个指针,该指针指向动态分配的连续内存空间地址,如果分配空间错误时,返回NULL。
- free():使用由指针ptr指向的内存区,使部分内存区能被其他变量使用,ptr是最近一次调用calloc或malloc函数时返回的值。
- 建立动态链表——逐个分配节点内存空间,然后输入节点中的数据并建立节点间相连关系
一:创建节点结构,表示每个学生 struct Student { char name[10]; int num; struct Student* pNext; }; 二:定义一个Create函数,用来创建列表,该函数将会返回链表的头指针: int iCount; struct Student* Create() { struct Student* pHead = NULL; struct Student* pEnd, *pNew; iCount = 0; pEnd = pNew = (struct Student*) malloc(sizeof(struct Student)); printf("please first enter Name,then Number\n"); scanf("%s",&pNew->name); scanf("%d",&pNew->num); while(pNew->num != 0) { iCount++; if(iCount == 1) { pNew->pNext = pHead; pEnd = pNew; pHead = pNew; } else { pNew->pNext = NULL; pEnd ->pNext = pNew; pEnd = pNew; } pNew = (struct Student*) malloc(sizeof(struct Student)); scanf("%s",&pNew->name); scanf("%d",&pNew->num); } free(pNew); free(pEnd ); }
- 输出链表
void Print(struct Student* pHead) { struct Student* pTemp; int iIndex = 1; printf("第%d个成员", iCount); printf("\n"); pTemp = pHead; while(pTemp != NULL) { printf("成员:%d是: \n", iIndex); printf("姓名:%s \n", pTemp->name); printf("学号:%d \n", pTemp->num); printf("\n"); pTemp = pTemp->pNext; iIndex++; } }
三、链表相关操作
3.1 🍚链表的插入
- 在链表的头节点位置插入节点
struct Student* Insert(struct Student* pHead) { struct Student* pNew; printf("插入一个成员\n"); pNew = (struct Student* )malloc(sizeof(Student)); scanf("%s",&pNew->name); scanf("%d",&pNew->num); pNew->pNext = pHead; pHead = pNew; iCount++; return pHead ; }
3.2 🍚链表的删除
void Delete(struct Student* pHead, int iIndex)
{
int i;
struct Student* pTemp;
struct Student* pPre;
pTemp = pHead;
pPre = pTemp;
printf("删除成员\n");
for(i = 0; i < iIndex; i++)
{
pPre = pTemp;
pTemp = pTemp->pNext;
}
pPre->pNext = pTemp->pNext;
free(pTemp);
iCount--;
}
struct Student
{
char name[10];
int num;
struct Student* pNext;
};
int iCount;
struct Student* Create()
{
struct Student* pHead = NULL;
struct Student* pEnd, *pNew;
iCount = 0;
pEnd = pNew = (struct Student*) malloc(sizeof(struct Student));
printf("please first enter Name,then Number\n");
scanf("%s",&pNew->name);
scanf("%d",&pNew->num);
while(pNew->num != 0)
{
iCount++;
if(iCount == 1)
{
pNew->pNext = pHead;
pEnd = pNew;
pHead = pNew;
}
else
{
pNew->pNext = NULL;
pEnd ->pNext = pNew;
pEnd = pNew;
}
pNew = (struct Student*) malloc(sizeof(struct Student));
scanf("%s",&pNew->name);
scanf("%d",&pNew->num);
}
free(pNew);
return pHead;
}
void Print(struct Student* pHead)
{
struct Student* pTemp;
int iIndex = 1;
printf("共%d个成员", iCount);
printf("\n");
pTemp = pHead;
while(pTemp != NULL)
{
printf("成员:%d是: \n", iIndex);
printf("姓名:%s \n", pTemp->name);
printf("学号:%d \n", pTemp->num);
printf("\n");
pTemp = pTemp->pNext;
iIndex++;
}
}
struct Student* Insert(struct Student* pHead)
{
struct Student* pNew;
printf("插入一个成员\n");
pNew = (struct Student* )malloc(sizeof(Student));
scanf("%s",&pNew->name);
scanf("%d",&pNew->num);
pNew->pNext = pHead;
pHead = pNew;
iCount++;
return pHead ;
}
void Delete(struct Student* pHead, int iIndex)
{
int i;
struct Student* pTemp;
struct Student* pPre;
pTemp = pHead;
pPre = pTemp;
printf("删除成员\n");
for(i = 0; i < iIndex; i++)
{
pPre = pTemp;
pTemp = pTemp->pNext;
}
pPre->pNext = pTemp->pNext;
free(pTemp);
iCount--;
}
main()
{
struct Student* pHead;
pHead = Create();
pHead = Insert(pHead);
Delete(pHead, 2);
Print(pHead);
printf("\n");
}