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 NodeDelete_x_node(struct Nodefirst,ElemType x)
{
//printf("%d,%s\n",LINE,FUNCTION);
struct Nodep=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文件:
main.c文件: