链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。链表都有一个头指针,一般以head来表示,存放的是一个地址。链表中的节点分为两类,头结点和一般节点,头结点是没有数据域的。链表中每个节点都分为两部分,一个数据域,一个是指针域。说到这里你应该就明白了,链表就如同车链子一样,head指向第一个元素:第一个元素又指向第二个元素;……,直到最后一个元素,该元素不再指向其它元素,它称为“表尾”,它的地址部分放一个“NULL”(表示“空地址”),链表到此结束。
作为有强大功能的链表,对他的操作当然有许多,比如:链表的创建,修改,删除,插入,输出,排序,反序,清空链表的元素,求链表的长度等等。
链表一般分为单向链表和双向链表,用的比较多的基本都是单向链表,以下讲解一下链表的一些基本操作。
建立有头结点的单向链表
有头结点的话上图中的第一个data域不存值,next指针域存的是第一个结点的地址,方便操作。当然不加头结点也可以,那就是直接在第一个结点的data域存值,一般来说,带有头结点的链表更为常见。
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int data;
struct node *next;
}node;
头插法建立单链表
头插法建立单链表的思想与插队类似,每一个新来的结点都插到前一个结点的前边,相当于每一个新来的结点都是除了头结点之外的第一个结点。
node *creat_linklist1()
{
node *H = (node *)malloc(sizeof(node));//申请头结点内存空间
H->next = NULL;//生成头结点
node *s;
int i;
scanf("%d",&i);
while(i != -1)
{
s = (node *)malloc(sizeof(node));//为每一个新的结点申请空间
s->data = i;
s->next = H->next;
H->next = s;
scanf("%d",&i);
}
return H;
}
使用头插法建立单链表时输入信息顺序与链表中存值的顺序相反。
尾插法建立单链表
尾插法建立单链表与顺序入队类似,每一个新来的结点都插到前一个结点的后边,
node *creat_linklist2()
{
node *H = (node *)malloc(sizeof(node));
node *r,*s;
r = H;
int i;
scanf("%d",&i);
while(i != -1)
{
s = (node *)malloc(sizeof(node));
s->data = i;
r->next = s;
r = s;
scanf("%d",&i);
}
r->next = NULL;
return H;
}
r->next=NULL;
这行代码一定不要忘,每次插入一个新的结点后一定要将此结点的next指针域置空,这也是与头插法区别的地方。
单链表的查找
·按序号查找
node *search_list1(node *H,int i)
{
node *p;
p = H;
int j = 0;
while(p->next != NULL && j < i)
{
p = p->next;
j++;
}
if(j == i)
return p;
else
return NULL;
}
·按数值查找
node *search_list2(node *H,int i)
{
node *p;
p = H->next;
while(p !=NULL && p->data != i)
p = p->next;
return p;
}
单链表结点的删除
删除的思想其实较为简单,只需要找到待删结点的前驱结点和后继结点,然后将前驱结点与后继结点相连,需要删除的结点就不在该链表之中了。
//链表数据的删除
void Delete_list(node *H,int i)
{
node *p,*q;
p = search_list1(H,i-1);//找到待删结点的前驱结点
if(p == NULL)
{
printf("第i-1个结点不存在\n");
return ;
}else if(p->next == NULL)
{
printf("第i个结点不存在\n");
return ;
}
else
{
q = p->next;//找到待删结点
p->next = q->next;//前驱结点与后继结点相连
free(q);//将删除后的结点内存空间释放掉
}
}
完整代码:
#include<stdio.h> //头文件
#include<stdlib.h>
typedef struct node
{
int data;
int wordlen;
struct node *next;
}node;
node *creat_linklist1();//头插法建立单链表
node *creat_linklist2();//尾插法建立单链表
void output(node *H);//遍历单链表
void Delete_list(node *H,int i);//删除结点
node *search_list1(node *H,int i);//查找(按序号)
node *search_list2(node *H,int i);//查找(按数值)
void Insert_list(node *H,int i,int x);//插入元素
int length_list(node *H);//求表长
void modify_list(node *H,int x,int y);//修改元素
void reverse_list(node *H);//逆置链表
int main()
{
int m = 0;
node *Head;
node *s,*r;
printf("请输入信息:\n");
Head = creat_linklist1();
//printf("插入信息前:\n");
//printf("删除前:\n");
//output(Head);
//s = search_list1(Head,3);
//r = search_list2(Head,4);
//printf("%d\n",s->data);
//printf("%d\n",r->data);
//Delete_list(Head,2);
//printf("删除后:\n");
//Insert_list(Head,3,5);
//printf("插入信息后:\n");
//m = length_list(Head);
//printf("%d",m);
//output(Head);
//printf("请输入要修改的信息:\n");
//modify_list(Head,5,9);
//reverse_list(Head);
//printf("逆置后的信息为:\n");
output(Head);
Delete_list(Head,2);
output(Head);
return 0;
}
//头插法建立单链表
node *creat_linklist1()
{
node *H = (node *)malloc(sizeof(node));
H->next = NULL;
node *s;
int i;
scanf("%d",&i);
while(i != -1)
{
s = (node *)malloc(sizeof(node));
s->data = i;
s->next = H->next;
H->next = s;
scanf("%d",&i);
}
return H;
}
//尾插法建立单链表
node *creat_linklist2()
{
node *H = (node *)malloc(sizeof(node));
node *r,*s;
r = H;
int i;
scanf("%d",&i);
while(i != -1)
{
s = (node *)malloc(sizeof(node));
s->data = i;
r->next = s;
r = s;
scanf("%d",&i);
}
r->next = NULL;
return H;
}
//链表的显示
void output(node *H)
{
node *r;
r = H->next;
printf("信息如下:\n");
while(r != NULL)
{
printf("%d ",r->data);
r = r->next;
}
}
//链表数据的删除
void Delete_list(node *H,int i)
{
node *p,*q;
p = search_list1(H,i-1);
if(p == NULL)
{
printf("第i-1个结点不存在\n");
return ;
}else if(p->next == NULL)
{
printf("第i个结点不存在\n");
return ;
}
else
{
q = p->next;
p->next = q->next;
free(q);
}
}
//链表数据的查找(按序号查找)
node *search_list1(node *H,int i)
{
node *p;
p = H;
int j = 0;
while(p->next != NULL && j < i)
{
p = p->next;
j++;
}
if(j == i)
return p;
else
return NULL;
}
//链表数据的查找(按数值查找)
node *search_list2(node *H,int i)
{
node *p;
p = H->next;
while(p != NULL && p->data != i)
p = p->next;
return p;
}
//链表数据的插入
void Insert_list(node *H,int i,int x)
{
node *p,*s;
p = search_list1(H,i-1);
if(p == NULL)
{
printf("插入位置错误\n");
return ;
}
else
{
s = (node *)malloc(sizeof(node));
s->data = x;
s->next = p->next;
p->next = s;
}
}
//求单链表的表长
int length_list(node *H)
{
node *p = H;
int j = 0;
while(p->next != NULL)
{
p = p->next;
j++;
}
return j;
}
//链表数据的修改
void modify_list(node *H,int x,int y)
{
node *p = H->next;
while(p != NULL)
{
if(p->data == x)
{
p->data = y;
}
p = p->next;
}
}
//单链表的逆置
void reverse_list(node *H)
{
node *p,*q;
p = H->next;
H->next = NULL;
while(p)
{
q = p;
p = p->next;
q->next = H->next;
H->next = q;
}
}
如出现错误还请各位在评论区指出,谢谢大家。