单向链表:
链表结点通常包含数据域与指针域,数据域用来存储相关的用户的数据,指针域用来指向下一个结点。访问单向链表,需要从头部(head)开始单向顺序访问,访问终结于指针域(next)为NULL的结点;其存储方式不同于以往的数组,按照非连续地址方式存储。
优点:
链表长度可以实现动态增长,不必像数组一样在创建时确定大小。
采取动态内存分配,不会造成内存浪费。
链表内部结点的插入与删除方便,只需修改相应的next指针。
在删除结点时,只需修改前一结点的指针,并释放本结点,不需要大量移动后面的元素。
实现:
结构体:
//结点结构体
#define Elemtype int
typedef struct node{
Elemtype value;//数据域
struct node *next;//指针域
}Node;
链表初始化:
//初始化头结点
//return:返回头结点指针
Node *create_list()
{
Node *head;
head = (Node *)malloc(sizeof(Node));//申请结点内存空间
if(!head)
{
printf("Error!");
exit(1);
}
head->next = NULL;
head->value = 0;
return head;
}
增加结点
//尾部增加结点
//@num:增加节点数量
//@head:头结点的地址
void add_node(int num,Node **head)
{
if(!*head)
{
printf("The list not create!\n");
return ;
}
Node *p,*q;//p指向新结点 q指向链表尾部
q = *head;
while(q->next != NULL)//遍历链表至尾部,在尾部插入新结点
q = q->next;
while(num--)
{
if(!(p = (Node *)malloc(sizeof(Node))))
{
printf("Error!\n");
exit(1);
}
p->next = NULL;
printf("input value:");
scanf("%d",&p->value);
q->next = p;//将新结点连接至链表尾部
q = p;//让q重新指向链表尾部
}
}
遍历打印
//遍历打印链表
//@head:头结点
void print_list(Node *head)
{
if(!head)
{
printf("The list not create!\n");
return ;
}
Node *p = head;
while(p->next)//当p的指针域为NULL时,此结点为尾结点
{
p = p->next;
printf("%d\n",p->value);
}
}
删除第N个结点
//删除第num个结点
//@num:被删除的结点
//@head:头结点
void delete_node(int num,Node **head)
{
if(!*head)
{
printf("The list not create!\n");
return ;
}
Node *q,*p = *head;
//循环中断条件
//当num == 0终止时,找到结点
//当p->next == NULL 终止时,链表长度小于或等于num
while(num-- && p->next != NULL)
{
if(!p->next && num > 0)//当p->next == NULL 且 num > 0时,链表长度小于num
{
printf("The length is less than num\n");
return ;
}
q = p;
p = p->next;
}
//循环正常结束后,执行到此处时,代表找到num结点。
q->next = p->next;
free(p);
p = NULL;
}
插入结点
//在num处后插入新结点
//@num:搜索的结点
//@value:新结点的值
//@head:头结点
void insert_node(int num,int value,Node **head)
{
if(!*head)
{
printf("The list not create!\n");
return ;
}
Node *q,*p = *head;
//循环中断条件
//当num == 0终止时,找到结点
//当p->next == NULL 终止时,链表长度小于或等于num
while(num-- && p->next != NULL)
{
if(!p->next && num > 0)//当p->next == NULL 且 num > 0时,链表长度小于num
{
printf("The length is less than num\n");
return ;
}
p = p->next;
}
q = (Node *)malloc(sizeof(Node));
q->value = value;
q->next = p->next;
p->next = q;
}
销毁链表
//销毁链表
//@head:头结点的指针
void destroy_list(Node **head)
{//因为要修改指针值,所以需要传递指针的指针(二级指针),类似于值传递与址传递
if(!*head)
{
printf("The list not create!\n");
return ;
}
Node *q = *head;
Node *p = *head;
//遍历删除头结点以外的结点
while(p->next)
{
p = p->next;
free(p);
p = q;
}
free(p);//删除头结点
p = NULL;
q = NULL;
*head = NULL;
}