无头结点链表

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 (first
NULL)
{
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 Node
last=NULL;
while (1)
{
scanf("%d",&num);
if (num0)
{
break;
}
struct Node*pnew=malloc(sizeof(struct Node));
pnew->data=num;
pnew->next=NULL;
if (first
NULL)
{
first=pnew;
last=pnew;
}
else
{
//1.先查找
struct Nodepre=NULL;
struct Node
p=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 Node
p=first;
struct Node
pre=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->data
x)
{
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 Node
Insert_node_1(struct Node first, ElemType x, ElemType y)
{
struct Node
p=first;
struct Nodepre=NULL;
struct Node
pnew=(struct Node*)malloc(sizeof(struct Node));
pnew->data=y;
pnew->next=NULL;
if (pNULL)
{
return first;
}
while §
{
if (p->data
x)
{
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 Node
Delete_all_x_node(struct Nodefirst,ElemType x)
{
struct Node
p=first;
struct Node*pre=NULL;
while §
{
if (p->datax)
{
if (p
first)
{
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 Node
first)
{
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 Node
Get_p_node(struct Nodefirst,int k)
{
//printf("%d,%s\n",LINE,FUNCTION);
struct Node
p=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 Node
first)//被释放的空间,再操作会产生段错误
{
struct Node*p=first;
while §
{
first=first->next;
p->next=NULL;
free§;//释放的是p指向的空间的内容
p=first;
}
p= NULL;

}

linklist.h文件:

头文件

main.c文件:

主调函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值