什么是链表:是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。
建立链表,先建结构体
struct student //学生结构体
{
char name[20]; //姓名
int number; //学号
struct student * next; //指向下一个结点的指针
};
一.创建create函数,功能:创建链表
指针变量:head头指针,end指向原来的尾节点,new指向新创建的节点
struct student * head = NULL; //初始化链表头指针为空
struct student * end,* new;
使用malloc将end,new分配内存
end = new = (struct student *)malloc(sizeof(struct student));
scanf("%s",new->name);
scanf("%d",&new->number);
用count++计算加入的节点个数
while(0 != new->number)
{
count++;
if(1 == count)
{
new->next = head; //使得指向为空
end = new; //跟踪新加入的结点
head = new; //头指针指向首结点
}
else
{
new->next = NULL; //新结点的指针为空
end->next = new; //原来的尾结点指向新结点
end = new; //end指向新结点
}
new = (struct student *)malloc(sizeof(struct student));//再次分配结点内存空间
scanf("%s",new->name);
scanf("%d",&new->number);
}
free(new); //释放没用到的空间
二.创建链表输出函数
head表示一个链表的头结点。
在函数中,定义一个临时的指针temp用来进行循环操作。定义一个整型变量表示链表中的结点序号。
然后将临时指针temp指针变量保存首结点的地址。
使用while语句将所有的结点中保存的数据都显示输出。其中每输出一个结点的内容后,就移动
temp指针变量指向下一个结点的地址。当最后一个结点时,所拥有的指针指向NULL,此时循环结束。
void print(struct student * head)
{
struct student *temp; //循环所用的临时指针
int index = 1; //表示链表中结点的序号
printf("---the list has %d members:---\n\n",count);
temp = head; //指针得到首结点的地址
while(NULL != temp)
{
printf("the NO%d member is:\n",index); //输出结点序号
printf("the name is:%s\n",temp->name); //输出姓名
printf("the number is:%d\n\n",temp->number); //输出学号
temp = temp->next; //移动临时指针到下一个结点
index++;
}
}
三.创建插入函数
在表头节点插入节点:创建new指针,分配空间,new指针下一节点指向原来的头节点head再指向新节点
conut再++就行了。
struct student * insert(struct student * head)
{
struct student * new; //指向新分配的空间
printf("---insert member at first---\n");
new = (struct student *)malloc(sizeof(struct student));//分配内存空间,并返回指向该内存空间的指针
scanf("%s",new->name);
scanf("%d",&new->number);
new->next = head; //新结点指针指向原来的首结点
head = new; //头指针指向新结点
count++; //增加链表结点数量
return head;
}
四.创建删除函数
函数两个传递参数,head和index,head为头指针,index为要删除的节点地址
然后定义两个变量,循环index次找到删除的节点位置和它的前节点,最后释放空间,count--。
void delete(struct student * head,int index)//head表示头结点,index表示要删除的结点下标
{
int i; //控制循环变量
struct student * temp; //临时指针
struct student * pre; //表示要删除结点前的结点
temp = head; //得到头结点
pre = temp;
printf("---delete NO%d member---\n\n\n",index);
for(i=1;i<index;i++) //for循环使得temp指向要删除的结点
{
pre = temp;
temp = temp->next;
}
pre->next = temp->next; //连接删除结点两边的结点
free(temp); //释放掉要删除结点的内存空间
count--; //减少链表中的元素个数
}