linklist.c文件:

#include<stdio.h>
 #include"linklist.h"
 struct Node* Create_LinkList()//Creat_Linklist:根据用户输入,创建一个单链表
 {
 ElemType num;
 struct Node* first=NULL;
 struct Node* last=NULL;
 while (1)
 {
 scanf("%d",&num);
 if (num0)
 {
 break; //出循环
 }
 struct Node* pnew=(struct Node* )malloc(sizeof(struct Node));
 pnew->data=num;
 pnew->next=NULL;
 if (firstNULL)
 {
 first=pnew;
 last=pnew;
 }
 #if 1 //尾插法
 {
 last->next=pnew;
 last=pnew;
 }
 #else //头插法
 {
 pnew->next=first;
 first=pnew;
 }
 #endif}
return first;//返回链表首地址}
/*
 Creat_Linklist:根据用户输入,创建一个有序链表
 返回值:返回首地址
/
 struct Node Creat_sort_linklist()
 {
 ElemType num;
 struct Nodefirst=NULL;
 struct Nodelast=NULL;
 while (1)
 {
 scanf("%d",&num);
 if (num0)
 {
 break;
 }
 struct Node*pnew=malloc(sizeof(struct Node));
 pnew->data=num;
 pnew->next=NULL;
 if (firstNULL)
 {
 first=pnew;
 last=pnew;
 }
 else
 {
 //1.先查找
 struct Nodepre=NULL;
 struct Nodep=first;
 while§
 {
 if (p->data>pnew->data)
 {
 break;
 }
 pre=p;
 p=p->next;
 }
 //再插入
 if §
 {
 if (p==first)
 {
 pnew->next=p;
 first=pnew;
 }
 else
 {
 pnew->next=p;
 pre->next=pnew;
 }
 }
 else//没有找到
 {
 pre->next=pnew;
 }
 }
 }
 return first;
 }/*


Insert_node:在一个链表中,在值为x的节点前面添加一个值为y的节点。
多个值为x的节点,则在第一个值为x的节点前面加
如果没有值为x的节点,则添加在最后
@first :要插入的链表的首地址
@x:要查找的节点的值
@y: 要插入的节点的值

返回值:
		返回值插入后新链表的首地址
*/
struct NodeInsert_node(struct Node first, ElemType x, ElemType y)
 {
 struct Nodep=first;
 struct Nodepre=NULL;
 struct Nodepnew=(struct Node)malloc(sizeof(struct Node*));//创建新节点
 pnew->data=y;
 pnew->next=NULL; 
 if (pNULL)//空链表
 {
 //return pnew;
 first=pnew;
 return first;
 }
 //2.查找值为x所在的节点的位置
 //两种方式出循环,(1)break,(2)尾结点=NULL,p=NULL;
 while (p!=NULL)
 {
 if (p->datax)
 {
 break;
 }
 pre=p;
 p=p->next;
 }
 //3.插入
 if §//p!=NULL
 {
 if (p==first)
 {
 pnew->next=p;
 first=pnew;
 }
 else
 {
 pnew->next=p;
 pre->next=pnew;
 }
 }
 else//没有找到,插在最后
 {
 pre->next=pnew;
 }return first;}
 /*
 Insert_node:在一个链表中,在值为x的节点前面添加一个值为y的节点。
 多个值为x的节点,则在第一个值为x的节点前面加
 如果没有值为x的节点,则添加在最后
 @first :要插入的链表的首地址
 @x:要查找的节点的值
 @y: 要插入的节点的值返回值:
		返回值插入后新链表的首地址/
 struct NodeInsert_node_1(struct Node first, ElemType x, ElemType y)
 {
 struct Nodep=first;
 struct Nodepre=NULL;
 struct Nodepnew=(struct Node*)malloc(sizeof(struct Node));
 pnew->data=y;
 pnew->next=NULL;
 if (pNULL)
 {
 return first;
 }
 while §
 {
 if (p->datax)
 {
 if(p==first)
 {
 pnew->next=p;
 first=pnew;
 }
 else
 {
 pnew->next=p;pre->next=pnew;
			 	}
			 break;//?
         }
		else
			{
			pre=p;
		    p=p->next;
			}			
	 }
 if (p==NULL)
	 {
	 pre->next=pnew;
	 }
 return first;}

/*
delete_x_node:在一个链表中,找到值为x的节点,将其删除,如果有多个值为X的节点,则删除值为x
的第一个节点。如果没有值为x的节点,则不删除。
@first:要删除的链表的首地址
@x:要删除的节点的值
返回值:删除节点后新链表的首地址(首节点的地址)
建议:先给要删除节点的前面节点找好下家,最后再把要删除结点的关系断掉
/
struct Node
Delete_x_node(struct Nodefirst,ElemType x)
{
//printf("%d,%s\n",LINE,FUNCTION);
struct Node
p=first;

struct Node*pre=NULL;
while (p)//保证p!=NULL
	{
	if (p->data==x)
		{
		break;
		}
	pre=p;
	p=p->next;
	}
//printf("__%d__,__%s__\n",__LINE__,__FUNCTION__);
if (p)
	{
	if (p==first)//要删除的是首节点
		{
		first=p->next;
		p->next=NULL;
		//free(p);//节点不是普通的存储空间,是malloc开辟的,要free
		}
	else
		{
		pre->next=p->next;//中间节点和尾节点的删除是一样
		p->next=NULL;
		//free(p);
		}
	free(p);
	}
//printf("__%d__,__%s__\n",__LINE__,__FUNCTION__);
return first;

}
/*
delete_all_x_node:在一个链表中,找到值为x的节点,将其删除。如果有多个值为x的节点,都删除。如果没有值为x的节点,则不删 除。
@first :要删除节点的链表的首地址
@x :要删除的节点的值

返回值:删除节点后新链表的首地址 
/
 //可以用递归
 struct NodeDelete_all_x_node(struct Nodefirst,ElemType x)
 {
 struct Nodep=first;
 struct Node*pre=NULL;
 while §
 {
 if (p->datax)
 {
 if (pfirst)
 {
 first=p->next;
 p->next=NULL;
 free§;
 p=first;
 }
 else
 {
 pre->next=p->next;
 p->next=NULL;
 free§;
 p=pre->next;
 }}
		pre=p;
		p=p->next;
	}
	return first;}
/*
 Get_node_num:计算链表的节点数
 返回值:节点数
/
 int Get_node_num(struct Nodefirst)
 {
 struct Nodep=first;
 ElemType num=0;
 while §
 {
 p=p->next;
 num++;
 }
 return num;
 }
 /
 写一个函数返回链表中倒数第k个节点的地址
 返回值:倒数第K个节点的地址
/
 /
 (1)倒序变顺序:
 求得整个链表的总数,减去k,这个就是遍历指针要移动的次数struct Node*Get_k_node(struct Node*first,int k)
		{
			//求得整个链表的总数
			int num = Get_node_num(first);
			
			//求得遍历指针移动的次数
			int n = num-k;
			if(n < 0)
			{
				return NULL;
			}
			
			struct Node*p = first;
			while(n)//3
			{
				p = p->next;
				n--;
			}
                             return p;
		}(2)哨兵法:q是哨兵,p是遍历指针,让哨兵比遍历指针先行k步,
 然后两个指针同时移动,循环到哨兵值为NULL时,
 遍历指针所指的位置就是倒数第k个节点的地址
 哨兵法:更高效,只需要一次遍历,但是要保证节点个数要大于k.
/
 struct NodeGet_p_node(struct Nodefirst,int k)
 {
 //printf("%d,%s\n",LINE,FUNCTION);
 struct Nodep=first;
 struct Node*q=first;
 while (k)
 {
 q=q->next;
 k–;
 }
 while (q)
 {
 q=q->next;
 p=p->next;
 }
 return p;}
void Print_linklist(struct Node* first)
 {
 struct Node* p=first;
 while §
 {
 printf("%d “,p->data);//p->data的用法
 p=p->next;
 }
 printf(”\n");
 }
 /*
 销毁链表:在某些情况,在创建完链表,使用链表的数据之后不再需要,
 为节省空间,要销毁链表
 @first:要销毁的链表
 返回值:返回销毁成功或失败 或则无返回值
/
 void destroy_linklist(struct Nodefirst)//被释放的空间,再操作会产生段错误
 {
 struct Node*p=first;
 while §
 {
 first=first->next;
 p->next=NULL;
 free§;//释放的是p指向的空间的内容
 p=first;
 }
 p= NULL;}

linklist.h文件:

java无头结点循环单链表 无头节点链表_链表

main.c文件:

java无头结点循环单链表 无头节点链表_链表_02