一、链表
1、链表和线性表的关系:链表是线性表的链式存储结构。
2、链表给每块数据单独的存储空间,即存储空间地址可不连续。
3、结点类型
struct node{
datatype data;
struct node *next;
};
二、单向链表
1、头结点不存储数据,且为空。
2、引入头结点的原因:在表头插入、表尾插入或者表中间插入都一样,让操作统一、简化。
三、用C语言实现单向链表
1、构造存储结构
typedef int datatype;
typedef struct linklist
{
datatype data; /* 数据域 */
struct linklist *next; /* 指针域 */
}link_list, *link_plist;
2、初始化
初始化主要的工作:①申请头结点空间;②建立空链表(
head->next=NULL
)
/* 初始化 */
void init_linklist(link_plist *list)
{
*list = (link_plist)malloc(sizeof(link_list));
if(NULL == *list)
{
printf("内存申请失败\n");
perror("malloc"); /* 打印内存申请失败原因 */
exit(1);
}
(*list)->next = NULL; /* 将next设为NULL,建立空链表 */
}
3、插入
插入主要工作:
第一步:把③的地址放到new->next
,即new->next = head->next
第二步:把①的next指向②(new
),即head->next = new
/* 插入 */
void insert_linklist(link_plist head, link_plist new)
{
new->next = head->next;
head->next = new;
}
4、删除
删除主要工作:
第一步:将pnode->next
连接到dnode->next
。
第二步:释放dnode
/* 删除 */
void delete_linklist(link_plist pnode)
{
link_plist dnode;
dnode = pnode->next; /* 没删除之前dnode的地址是pnode->next */
pnode->next = dnode->next;
free(dnode);
}
5、判断链表是否为空
判断链表是否为空只需判断
head->next
是否为NULL
即可。
/* 判断是否为空 */
bool isempty(link_plist head)
{
if(NULL == head->next)
{
return true;
}
else
{
return false;
}
}
四、练习题
用单向链表实现数据逆转,首先建立一个包含若干整数的单向链表,然后参考讲义的例子实现数据的逆转。(比如说把1,2,3,4,5逆转成5,4,3,2,1)。
1、逆转思路
①、linklist p, t;
,p
用于指向下一个结点,t
用于临时保存结点数据。
②、让p = head->next;
,也就是一开始让为头结点的下一个结点,也就是第一个保存数据的结点,这里也就是保持数据1
的结点,如下图所示。
③、让head->next = NULL;
,也就是让头结点与其它结点断开,如下图所示:
④、用t
来保存p
结点的数据(t = p;
),也就是此时t
已经保存了第1个结点的数据,然后让p
指向下一个结点p = p->next;
,p
已经来到了第2个结点,接着再将t
插入到链表,也就插入第1个结点,因为前面head->next = NULL;
,因此插入后如下图所示:
⑤、现在p
结点时是指向第二个结点,再让t = p;
,p = p->next;
,也就是t
已经保存第2个结点的数据了,p
已经指向第3个结点了,如下图所示:
⑥、现在让t
插入到链表中,根据我们前面讲的链表插入,t
是插入到head
与第一个结点直接的,如下图所示:
⑦、因此,插入后链表就变成如下图所示:
⑧、按照这个思路下去,最终就能完成逆转了,如下图所示:
⑨、逆转的代码如下:
link_plist p = NULL;
link_plist t = NULL;
p = head->next;
head->next = NULL;
while(p != NULL)
{
t = p;
p = p->next;
insert_linklist(head, t);
}
2、创建单向链表
/* 创建单向链表 */
void create_linklist(link_plist head)
{
link_plist new = NULL;
link_plist p = head;
int len = 0;
int i = 0;
printf("输入要插入数据的个数:");
scanf("%d", &len);
for(i = 0; i < len; i++)
{
new = (link_plist)malloc(sizeof(link_list));
if(NULL == new)
{
printf("内存申请失败\n");
perror("malloc");
exit(1);
}
printf("输入要插入的第%d个数据:", (i+1));
scanf("%d", &(new->data));
insert_linklist(p, new);
p = p->next;
show_linklist(head); /* 打印 */
}
}
3、逆转数据
/* 将数据逆转 */
void sort_linklist(link_plist head)
{
link_plist p = NULL;
link_plist t = NULL;
p = head->next;
head->next = NULL;
while(p != NULL)
{
t = p;
p = p->next;
insert_linklist(head, t); /* 这里实现的是在head后面插入结点,看不明白可看前面插入思路 */
show_linklist(head);
}
}
4、主函数main.c
:
int main(void)
{
link_plist head; /* 定义一个头指针 */
init_linklist(&head); /* 初始化 */
create_linklist(head); /* 创建单向链表 */
sort_linklist(head); /* 逆转 */
return 0;
}
5、测试结果: