目录
C语言链表学习
概念
链表是一种常见的数据结构。相对于数组,链表存储元素的个数是不受限定的,当进行添加或删除元素时,存储的个数就会随之改变。
链表中有一个头指针变量,这个指针变量保存一个地址。也就是说头指针指向一个变量,这个变量称为元素。链表中每一个元素包括数据部分和指针部分。数据部分用来存放元素所包含的数据,而指针部分用来指向下一个元素。最后一个元素的指针指向NULL,表示指向的地址为空。
一、创建动态链表
链表并不是一开始就设定好自身的大小,而是根据节点的多少来决定的,因此链表的创建过程时动态的创建过程。动态创建一个节点时,需要为其分配内存,在介绍如何创建链表前,需要先了解一些有关动态创建会使用的函数。
相关函数介绍
1. malloc函数
malloc函数原型如下:
void *malloc(unsigned int size);
该函数的功能是在内存中动态地分配一块size大小的内存空间。malloc函数会返回一个指针,该指针指向分配的内存空间,如果出现错误则返回NULL。
2.calloc函数
calloc函数原型如下:
void *calloc(unsigned n,unsigned size);
该函数的功能是在内存中动态分配n个长度为size的连续内存空间数组。calloc函数会返回一个指针,该指针指向动态分配的连续内存空间地址。当分配空间错误时,返回NULL。
3.free函数
free函数原型如下:
void free(void *ptr);
该函数的功能是使用由指针ptr指向的内存区,使部分内存区能被其他变量使用。ptr是最近一次调用calloc或malloc函数时返回的值。free函数无返回值。
动态链表创建
1.创建节点结构
struct student
{
charname[20]; //姓名
int num; //学号
struct student* pNext; //指向下一个节点的指针
}
2.定义一个函数,用来创建链表
定义一个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->cName);
scanf("%d"&pNew->iNumber);
while(pNew->iNumber!=0)
{
iCount++;
if(iCount==1)
{
pNew->pNext=pHead; /*使得指向为空*/
pEnd=pNew; /*跟踪新加入的节点*/
pHead=pNew; /*头指针指向首节点*/
}
else
{
pNew->pNext=NULL; /*新节点的指针为空/
pEnd->pNext=pNew; /*原来的尾节点指向新节点*/
pEnd=pNew; /*pEnd指向新节点*/
}
pNew=(struct Student*)malloc(sizeof(struct Student)); /“再次分配节点内存空间*/
scanf("%s"&pNew->cName);
scanf("%d"&pNew->iNumber);
}
free(pNew); /*释放没有用到的空间*/
return pHead;
}
create函数的功能是创建链表,在create的外部可以看到一个整型的全局变量iCount,这个变量的作用是表示链表中节点的数量。在create函数中,首先定义需要用到的指针变量,pHead用来表示头指针,pEnd用来指向原来的尾节点,pNew用来指向新创建的节点。
使用malloc函数分配内存,先用pEnd和pNew两个指针都指向第一个分配的内存,然后显示提示信息,先输出一个学生的姓名,再输入学生的学号。使用while语句进行判断,如果学号为0,则不执行循环语句。
在while循环语句中,iCount++自加操作表示链表中节点的增加。然后要判断新加入的节点是否是第一次加入的节点,如果是第一次加入,则执行if语句块中的代码,否则应执行else语句块中的代码。
在if语句块中,因为第一次加入节点时其中没有节点,所以新节点即为首节点,也为最后一个节点,并且要将新加入的节点的指针指向NULL,即为pHead指向。else语句实现的是链表中已经由节点存在时的操作。首先将新节点pNew的指针指向NULL,然后将原来最后一个节点的指针指向新节点,最后将pEnd指针指向最后一个节点。
一个节点创建完之后,要进行内存分配,然后向其中输入数据,通过while语句再次判断输入的数据是否符合节点的要求。当节点不符合要求时,执行下面的代码,即调用free函数将不符合要求的节点空间进行释放。
二、链表相关操作
1.链表的插入
头插法
Pnew->next = headNode->next;
headNode->next = Pnew;
尾插法
struct Node *headNode;
while(headNode)
{
headNode = headNode->next;
}
if(headNode)
{
struct Node *s =(struct Node*)malloc(sizeof(struct Node));
headNode->next = s;
head = s;
//增添的相关信息
//eg.scanf("%d",s->结构体中的相关的变量);
headNode->next = NULL; //s->next = NULL;
}
任意位置插入
struct Node *temp = headNode;
int n //想要插入的位置
int i;
for(i = 0;i<n;i++)
{
temp = temp->Next ;
}
struct Node *Pnew = (struct Node *)malloc(sizeof(struct Node));
Pnew->Next = temp->Next ;
temp->Next = Pnew;
2.链表的删除
示例:
void Delete(struct Student* pHead,int ilndex) /*pHead表示头节点,ilndex表示要删除的节点下标*/
{
int i; /*控制循环变量*/
struct Student* pTemp; /*临时指针*/
struct Student* pPre; /*表示要删除节点前的节点*/
pTemp=pHead; *得到头节点*/
pPre=pTemp;
printf("----delete NO%d member----n"ilndex):/*提示信息*/
for(i=1;i<ilndex;i++) /*for循环使得pTemp指向要删除的节点*/
{
pPre=pTemp;
pTemp=pTemp->pNext;
}
pPre->pNext=pTemp->pNext; /*连接删除节点两边的节点*/
free(pTemp); /*释放掉要删除节点的内存空间*/
iCount--; /*减少链表中的元素个数*/
}