为什么要使用链表,因为链表可以连接数据类型不一样的数据,而一个数组中只能使用一种数据类型。
以学生为例:
一个学生有学号,姓名,年龄,性别,等,先拿这四个用着。开始下面的内容:
1、创建链表
首先我们要创建单链表中的每一个结点模型,就是创建一个结点模型,后面要用就往里面填数据就行。链表的结点有两个域,一个是值域,一个是指针域,指针域就是指向下一个链表的位置。所以我们要使用结构体来定义这两个域中的变量。看代码:
然后需要头指针,这个头指针的类型也必须是这个结构体指针类型,指针也是有类型的,所以我们还需要定义结构体指针类型,看代码:
这里需要注意的是第一个定义的是结构体变量,第二个定义的是结构体指针类型就是要这样看:
这里是为了方便后面少些点,所以就在这里定义,用Link代表Node *,后面再用Link来定义该类型的指针变量。
到这里我们就需要创建链表了,起始创建的是一个空链表:
就是定义一个头指针(Link head = NULL),这个头指针指向空,说明是一个空链表,必须给指针变量有明确的指向,不能没有指向。(防止出现野指针)。创建链表实参是地址(指针),形参要用二级指针来接,看代码
我们链表创建完成,然后就是创建结点了,这个结点就是上面定义的结构体,他是个模型,所以要定义一个结构体指针来指向将要分配给它内存的首地址,现在我们要给它分配内存和赋值了,这里分配内存时用malloc动态分配的,后面需要将这个内存回收。看代码:
这里函数的参数时二级指针,二级指针是对数据的地址进行操作,一级指针是对数据本身进行操作。
结点创建完成并赋值,这里为了方便就给num进行赋值,其余先不管:
以上就是链表的创建,现在有了头指针,有了第一个要插入的结点,下面就要进行插入操作。
2、插入
编写插入函数在主函数里调用
这里插入有三种方法,头插法,尾插法和中间插法
首先看头插法:
注意头插法需要不断的修改头指针所指向的地址,所以函数的形参要用二级指针。然后就是指针指向的变动了,上面一共形成十个同学的数据,所以有十个结点。
这个就是头插法。
尾插法
尾插法就是在链表的最后一个结点后插上新的结点。
中间插法
中间插入法需要定义两个结构体类型的指针变量p和q,指向头指针指向的地址。后面就是根据要插入结点位置,来确定q和p的指向,然后进行插入
删除和查找后续加上。
以下是链表的创建和插入源代码:
#include <stdio.h>
#include <stdlib.h>
/*
* 链表的中间插法
*
* 创建单链表步骤:
*1、单链表有指针域和值域,先创建值域和指针域
*2、定义一个结构体类型和结构体的指针类型
*3、有了指针创建链表
*4、链表没有结点在创建结点
*5、插入结点
*6、释放空间
*
*/
//创建链表结点,结构体包含值域和指针域
struct node
{
int num;
char name;
struct node *next; //指针域
};
typedef struct node Node; //定义结构体变量名
typedef Node * Link; //定义结构体指针类型
//创建链表
void create_link(Link *head)
{
*head = NULL; //空链表
}
//创建结点
void create_node(Link *new_node)
{
*new_node = (Link)malloc(sizeof(Node));
}
//尾插法函数
void insert_node_tail(Link *head, Link new_node)
{
Link p = NULL;
p = *head;
if(NULL == p)
{
*head = new_node;
new_node->next = NULL;
}
else
{
while( p->next != NULL)
{
p = p->next;
}
p->next = new_node;
new_node->next = NULL;
}
}
//头插法函数
void insert_node_head(Link *head, Link new_node)
{
new_node->next = *head;
*head = new_node;
}
//中间插入法函数
void insert_node_mid(Link new_node, Link *head, int loc)
{
Link p = NULL;
Link q = NULL;
p = q = *head;
while( p != NULL && p->num != loc)
{
q = p;
p = p->next;
}
if(p == *head)
{
new_node->next = *head;
*head = new_node;
}
else
{
q->next = new_node;
new_node->next = p;
}
}
//列出链表
void display_link(Link head)
{
Link p = NULL;
p = head;
while( p != NULL)
{
printf("%d\n",p->num);
p = p->next;
}
}
//释放结点空间
void release_link(Link *head)
{
Link p = NULL;
p = *head;
while(*head != NULL)
{
*head = (*head)->next;
free(p);
p = *head;
}
if(*head == NULL)
{
printf("link is empty!");
}
printf("\n");
}
int main(int argc, char **argv)
{
//定义一个头指针
Link head = NULL;
Link new_node = NULL;
int i;
int loc;
//创建链表
create_link(&head);
printf("please input loc:\n");
scanf("%d",&loc);
printf("please input num:\n");
for(i = 0; i < 10; i++)
{
create_node(&new_node);
new_node->num = i + 1;
insert_node_tail(&head, new_node);
}
/* for(i = 0; i < 10; i++)
{
create_node(&new_node);
new_node->num = i + 1;
insert_node_head(&head, new_node);
}
*/
//创建新结点
create_node(&new_node);
scanf("%d",&new_node->num);
//插入结点
insert_node_mid(new_node, &head, loc);
//列出链表
display_link(head);
//释放空间
release_link(&head);
return 0;
}