带头节点的单向不循环链表

//filename:single_list.h
#ifndef _SINGLE_LIST__H
#define _SINGLE_LIST__H
#include "stdio.h"
#include "stdlib.h"
//带头节点单向不循环链表

typedef int datatype;

typedef struct slist{
	datatype dat;
	struct slist* next;
}s_node;
//不论是向第i个节点插入还是删除,都要在第(i-1)个节点上进行操作

//思路:malloc一个节点作为头节点,头节点的next指向null
s_node* slist_create(void);//创建一个单向带头节点不循环链表

//思路:定义一个指针p,从头节点开始遍历,遍历条件是p非空且跳过节点数小于i,则遍历结束时p为空或者p是第(i-1)个节点,此时插入新节点
int slist_insert_at(s_node* list,int i,datatype* dat);//向第i个节点插入dat

//思路:定义一个指针p,从头节点开始遍历,遍历条件是p非空且跳过节点数小于i,则遍历结束时p为空或者p是第(i-1)个节点,先保存(i+1)节点,再删除i节点
int slist_delete_at(s_node* list,int i,datatype* dat);//删除第i个节点,i从0开始

//思路:定义一个指针p,从头节点开始遍历,遍历条件是p->next非空且p->dat小于dat,则遍历结束时p为空或p->dat大于dat的节点,此时插入新节点
int slist_insert_order(s_node* list,datatype* dat);//按照dat大小顺序插入

//思路:定义一个指针p,从头节点开始遍历,直到p->next为空则结束遍历,插入新节点
int slist_insert_tail(s_node* list,datatype* dat);//向尾部插入

//思路:直接向头节点后面插入
int slist_insert_first(s_node* list,datatype* dat);//向首部插入

//思路:定义一个指针p_prev,从头节点开始遍历,直到p->next为空则结束遍历,p_prev是记录p->next为空的上一个节点,释放p,p_prev->next=null
int slist_delete_tail(s_node* list,datatype* out_dat);//删除尾部节点,注意头节点不会被删除

//思路:删除头节点后面的节点
int slist_delete_first(s_node* list,datatype*out_dat);//删除第0个节点

//思路:定义一个指针p,从头节点开始遍历,遍历条件是p->next非空且p->dat等于dat,则遍历结束时p为空或p->dat等于dat的节点,此时删除节点
int slist_delete(s_node* list,datatype* dat);//删除dat节点

//思路:定义一个指针p,从头节点开始遍历,num累计,遍历条件是p->next非空且p->dat等于dat,则遍历结束时p为空或p->dat等于dat的节点,此时返回num
int slist_find(s_node* list,datatype* dat);//find dat节点号

//思路:头节点的next为null则链表为空
int slist_isempty(s_node* list);//判断链表是否为空

//思路:根据节点的next遍历
void slist_show(s_node* list);//遍历显示node

//思路:根据节点的next遍历释放节点,注意释放前要保存下一个节点
void slist_destroy(s_node* list);//销毁链表

#endif
//filename:single_list.c
#include "single_list.h"


s_node* slist_create(void)
{
	s_node* plist = NULL;
	plist = malloc(sizeof(s_node));
	if(plist == NULL)
		return NULL;
	plist->next = NULL;
	return plist;
}//创建一个单向带头节点不循环链表

int slist_insert_at(s_node* list,int i,datatype* dat)
{
	if(i<0) return -1;
	
	s_node* p = list;//这里不能为list->next,否则开始时第0个插不进
	int j=0;
	while(p!= NULL && j<i)
	{
		//printf("debug %p\n",p->next);
		p=p->next;
		j++;
	}
	
	if(p==NULL) return -2;//例如只有5个节点,但是i大于5
	else   //p is (i-1) node
	{
		s_node* insert_node = slist_create();
		if(insert_node == NULL) return -3;
		
		insert_node->dat = *dat;//data
		insert_node->next = p->next;
		p->next = insert_node;
	}
	return 0;
	
}//向第i个节点插入dat

int slist_delete_at(s_node* list,int i,datatype* out_dat)
{
		if(i<0) return -1;
		s_node*p = list;
		int j=0;
		while(p!=NULL && j<i)
		{
			p=p->next;
			j++;
		}
		if(p==NULL) return -2;
		else //p is (i-1) node
		{
			s_node* del_node;
			del_node = p->next;
			if(out_dat!= NULL) *out_dat = del_node->dat;
			p->next = del_node->next;
			free(del_node);del_node=NULL;
		}
	return 0;
}//删除第i个节点,i从0开始


int slist_insert_order(s_node* list,datatype* dat)
{
		s_node * p=list;
		s_node* insert_node;
			
		while(p->next!=NULL)
		{
			if(p->next->dat > *dat)break;
			p=p->next;
		}
		
		insert_node = slist_create();
		if(insert_node == NULL) return -1;
		insert_node->dat = *dat;
		insert_node->next = p->next;
		p->next = insert_node;
		
		return 0;
}//按照dat大小顺序插入,从小到大顺序

int slist_insert_tail(s_node* list,datatype* dat)
{
	s_node *p=list;
	s_node *insert_node;
	while(p->next != NULL)
	{
			p=p->next;
	}
	
	insert_node = slist_create();
	if(insert_node == NULL) return -1;
	insert_node->dat = *dat;
	insert_node->next=p->next;
	p->next=insert_node;
	return 0;
}//向尾部插入

int slist_insert_first(s_node* list,datatype* dat)
{
	s_node *p=list;
	s_node *insert_node;
	
	insert_node = slist_create();
	if(insert_node == NULL) return -1;
	insert_node->dat = *dat;
	insert_node->next=p->next;
	p->next=insert_node;	
}//向首部插入

int slist_delete_tail(s_node* list,datatype* out_dat)
{
	s_node *p=list;
	s_node *p_prev;
	
	if(slist_isempty(p)==1) return -1;
	
	p_prev=p;
	while(p->next != NULL)
	{
		p_prev=p;
		p=p->next;
	}
	//p->next==NULL
	if(out_dat!=NULL) *out_dat = p->dat;
	free(p);
	p_prev->next=NULL;
	return 0;
}//删除尾部节点,注意头节点不会被删除

int slist_delete_first(s_node* list,datatype*out_dat)
{
	s_node*p=list;
	s_node *p_next;
	if(slist_isempty(p)==1) return -1;
	p_next = p->next->next;
	if(out_dat!=NULL) *out_dat = p->next->dat;
	free(p->next);
	p->next = p_next;
	return 0;
}//删除第0个节点

int slist_delete(s_node* list,datatype* dat)
{
	if(dat == NULL) return -1;
	
	s_node*p=list;
	s_node*p_next;
	while(p->next !=NULL)
	{
		if(p->next->dat == *dat) break;
		p=p->next;
	}		
	if(p->next == NULL) return -2;
	//p is *dat prev node
	p_next=p->next;
	p->next=p_next->next;
	free(p_next);
	return 0;
}//删除dat节点

int slist_find(s_node* list,datatype* dat)
{
	if(dat == NULL) return -1;
	int num=0;
	s_node*p=list;
	s_node*p_next;
	while(p->next !=NULL)
	{
		if(p->next->dat == *dat) break;
		num++;
		p=p->next;
	}		
	if(p->next == NULL) return -2;
	return num;
	
}//find dat节点号

int slist_isempty(s_node* list)
{
	if(list->next==NULL)return 1;
	return 0;
}//判断链表是否为空

void slist_show(s_node* list)
{
	if(slist_isempty(list)==1) return;
	s_node* p = list->next;
	for(;p!=NULL;p=p->next)
	{
		printf("%d ",p->dat);
	}
	printf("\n");
}//遍历显示node

void slist_destroy(s_node* list)
{
	s_node * p;
	s_node * p_next;
	for(p=list->next;p!=NULL;p=p_next)
	{
		p_next=p->next;
		//printf("free %d\n",p->dat);
		free(p);p=NULL;
	}
	free(list);list=NULL;//free head
}//销毁链表

//filename:main.c
#include "single_list.h"
datatype arr[10]={12,34,56,23,56,1,34,24,90,76};
datatype arr1[10]={24,34,6,23,6,1,100,51,90,0};
int main(int argc ,char*argv[])
{
	//-----------------------------------
	printf("特定位置插入、删除\r\n");
	s_node* L= slist_create();
	if(L==NULL) goto exit;
	int i,ret;
	for(i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
	{
		if((ret = slist_insert_at(L,i,&arr[i]))!=0)
		{
			printf("err:%d\n",ret);
			goto exit;
		}
	}
	slist_show(L);
	datatype dat;
	slist_delete_at(L,0,&dat);
	printf("del: %d\n",dat);
	slist_delete_at(L,3,&dat);
	printf("del: %d\n",dat);
	slist_delete_at(L,7,&dat);
	printf("del: %d\n",dat);	
	slist_show(L);
	slist_destroy(L);
	printf("\r\n");
	//-----------------------------------
	printf("按顺序插入\r\n");
	s_node* L1= slist_create();
	if(L1==NULL) goto exit;
	for(i=0;i<(sizeof(arr1)/sizeof(arr1[0]));i++)
	{
		if((ret = slist_insert_order(L1,&arr1[i]))!=0)
		{
			printf("err:%d\n",ret);
			goto exit;
		}
	}
	slist_show(L1);
	printf("\r\n");
	
	dat = 15;
	printf("尾部插入 %d \r\n",dat);
	slist_insert_tail(L1,&dat);//尾部插入
	slist_show(L1);
	printf("\r\n");
	
	dat = 33;
	printf("首部插入 %d \r\n",dat);
	slist_insert_first(L1,&dat);//0节点插入
	slist_show(L1);
	printf("\r\n");
	
	slist_delete_tail(L1,&dat);//尾部删除
	printf("尾部删除 %d \r\n",dat);
	slist_show(L1);
	printf("\r\n");
	
	slist_delete_first(L1,&dat);//0节点删除
	printf("首部删除 %d \r\n",dat);
	slist_show(L1);
	printf("\r\n");
	
	dat = 0;
	printf("删除%d \r\n",dat);
	slist_delete(L1,&dat);
	slist_show(L1);
	printf("\r\n");

	
	dat = 6;
	printf("删除%d \r\n",dat);
	slist_delete(L1,&dat);
	slist_show(L1);
	printf("\r\n");	

	dat = 100;
	printf("删除%d \r\n",dat);
	slist_delete(L1,&dat);
	slist_show(L1);
	printf("\r\n");	

	dat = 200;
	printf("删除%d \r\n",dat);
	slist_delete(L1,&dat);
	slist_show(L1);
	printf("\r\n");		
	
	int num;
	dat = 200;num=-1;
	if((num = slist_find(L1,&dat))>=0)
		printf("发现%d节点编号%d\r\n",dat,num);
	else
		printf("%d节点不在链表中\r\n",dat);
	slist_show(L1);
	printf("\r\n");	

	dat = 1;num=-1;
	if((num = slist_find(L1,&dat))>=0)
		printf("发现%d节点编号%d\r\n",dat,num);
	else
		printf("%d节点不在链表中\r\n",dat);
	slist_show(L1);
	printf("\r\n");	
	
	dat = 6;num=-1;
	if((num = slist_find(L1,&dat))>=0)
		printf("发现%d节点编号%d\r\n",dat,num);
	else
		printf("%d节点不在链表中\r\n",dat);
	slist_show(L1);
	printf("\r\n");	
	
	dat = 90;num=-1;
	if((num = slist_find(L1,&dat))>=0)
		printf("发现%d节点编号%d\r\n",dat,num);
	else
		printf("%d节点不在链表中\r\n",dat);
	slist_show(L1);
	printf("\r\n");	
	
	slist_destroy(L1);
	
exit:
	return 0;
}

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
带头结点的单向循环链表可以通过以下步骤进行建立: 1. 定义链表节点结构体,包含数据域和指向下一个节点的指针; 2. 定义一个指向链表首节点的指针,初始值为NULL; 3. 读入第一个节点的数据,创建一个节点,将其作为链表首节点,指向自身,将其指针赋值给链表首指针; 4. 读入下一个节点的数据,创建一个节点,将其插入到链表的尾部,即将链表尾节点的指针指向新节点,新节点的指针指向首节点,完成插入操作; 5. 重复执行步骤4,直到读取完所有节点的数据。 具体实现可以参考以下代码: ```c typedef struct Node { int data; // 数据域 struct Node *next; // 指向下一个节点的指针 } Node; int main() { Node *head = NULL; // 链表首指针初始化为NULL Node *tail = NULL; // 链表尾指针初始化为NULL int n; // 节点个数 int data; // 数据 scanf("%d", &n); // 读入节点个数 for (int i = 0; i < n; i++) { scanf("%d", &data); // 读入节点数据 Node *node = (Node*)malloc(sizeof(Node)); // 创建新节点 node->data = data; // 赋值数据域 node->next = NULL; // 新节点的next指针初始化为NULL if (head == NULL) { // 如果链表为空,将新节点作为首节点 head = node; node->next = head; // 新节点的next指针指向自身 tail = head; // 将尾指针指向首节点 } else { // 如果链表不为空,将新节点插入到尾部 node->next = head; // 新节点的next指针指向首节点 tail->next = node; // 将尾节点的next指针指向新节点 tail = node; // 将尾指针指向新节点 } } return 0; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值