C语言单链表(数据结构与算法篇)

链表是一种常见的基础数据结构,结构体指针在这里得到了充分的利用。链表可以动态的进行存储分配,也就是说,链表是一个功能极为强大的数组,他可以在节点中定义多种数据类型,还可以根据需要随意增添,删除,插入节点。链表都有一个头指针,一般以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;
	}	
} 

如出现错误还请各位在评论区指出,谢谢大家。

猜你喜欢

转载自blog.csdn.net/irving725/article/details/112940976