typedef struct node//该结构体代表一个结点
{
int data; //结点的数据域
struct node *next; //结点的指针域
}lnode,*linklist; //定义一个结构体变量和指向结构体的指针
//用头插法创建一个链表
linklist create_begin()
{
linklist head=(linklist)malloc(sizeof(lnode));//定义头结点并开辟空间
head->next=NULL; //为避免指针乱指,将头结点下一个指针赋空
int x;
printf("please input the data:\n");
scanf("%d",&x);
while(x!=-1) //数据为-1时停止继续输入
{
lnode *s=(linklist)malloc(sizeof(lnode));//s指向要插入的新结点,并为它开辟空间
s->data=x;
s->next=head->next; //将s结点的next指针 指向 头结点next指针 所指向的空间
head->next=s; //将头结点的next指针指向s结点,实现头插
printf("please input the data:\n");
scanf("%d",&x);
}
return head;
}
linklist create_end()
{
linklist head=(linklist)malloc(sizeof(lnode));//定义头结点并开辟空间
head->next=NULL; //为避免指针乱指,将头结点下一个指针赋空
lnode *p=head,*s; //定义指向结构体的p指针和s指针,使p指针指向头指针所指向的
int x;
printf("please input the data:\n");
scanf("%d",&x);
while(x!=-1) //数据为-1时停止继续输入
{
s=(linklist)malloc(sizeof(lnode));//s指向要插入的新结点,并为它开辟空间
s->data=x;
s->next=p->next; //新结点的next指针指向p结点next指针所指向的,且p结点的next始终为空
p->next=s; //p结点的next指向新结点
p=s; //p指向s所指向的,确保p指针指向的结点始终为最后一个结点
printf("please input the data:\n");
scanf("%d",&x);
}
return head;
}
//打印结点中的数据
void print(lnode *p)
{
p=p->next;
while(p)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
//查找链表中的结点,按照结点在链表中的次序查找,x代表顺序,默认头结点的下一个为1
linklist findone(linklist p,int x)
{
p=p->next;//p从第一个结点开始查找
int j=1;//记录结点数
while(p)
{
if(j==x)
return p;
p=p->next;
j++; //指针每后移一次结点数+1
}
return NULL;//循环跳出代表p指针为空,即没有查找到次序为x的结点
}
//查找链表中的结点,按照结点中的数据查找,x代表具体数据
linklist findtwo(linklist p,int x)
{
p=p->next;
while(p)
{
if(p->data==x)
return p; //找到则返回该结点
p=p->next;
}
return NULL;//遍历结束则返回空
}
//向链表中插入数据,i代表插入的位置,x代表插入的具体数据
int insert(linklist head,int i,int x)
{
lnode *p,*s;
p=findone(head,i-1);//要向指定位置插入新结点,必须找到指定位置的直接前驱结点,所以用p指向要插入位置的直接前驱结点
if(p==NULL)
{
return false;//找不到直接前驱结点,插入失败
}
else
{
s=(linklist)malloc(sizeof(lnode));
s->data=x;
s->next=p->next;//要插入的结点s的next指针指向直接前驱结点的next指针所指向的结点,即指向当前要插入位置所在的结点
p->next=s; //直接前驱结点的next指针指向新结点
return true;//插入成功
}
}
//删除链表中的指定位置结点,head为头指针,i为要删除结点在链表中的次序
int del(linklist head,int i)
{
lnode *p,*s;
p=findone(head,i-1); //p指向要删除结点的前一个结点是否存在
//判断要删除结点的前一个结点是否存在
if(p==NULL)
{
return false;
}
else
{
//判断要删除结点(p->next)是否存在
if(p->next==NULL)
{
return false;
}
else
{
s=p->next; //s指向要删除的结点
p->next=s->next;//p的next指向s的next指向的结点
free(s); //释放s结点的空间
return true;
}
}
}
//链表的倒置,思路:依次取原链表的每个结点,用头插法插入到新的链表中
void reserve(linklist head)
{
lnode *p,*s;
p=head->next;
head->next=NULL;//创建一个新链表
//p指向当前结点,判断p是否为空
while(p)
{
//s表示要插入的结点,p用来标记下一个要插入的结点,防止丢失
s=p;
p=p->next;
//用头插法依次插入
s->next=head->next;
head->next=s;
}
}
//删除链表中重复的结点,思路:利用两个循环,p指向第一个结点,从它直接后继结点开始查找和它相同的结点,找到则删除,然后p依次向下指,直到最后结点
void del_same(linklist head)
{
lnode *p,*s,*r;
p=head->next;
if(p!=NULL)
while(p->next)//判断p的下一个结点是否存在
{
s=p;
while(s->next)//从p的后继结点开始循环查找,此处和删除结点类似,必须要知道要删结点的直接前驱,如果找到相同的结点,s为直接前驱
{
if(s->next->data==p->data)
{
r=s->next;
s->next=r->next;
free(r);
}
else
{
s=s->next;//依次向后遍历
}
}
if(p->next!=NULL)//如果p的下一个结点不为空,p指向下一个结点,否则的话,p指向空,循环条件(p->next)会出错
p=p->next;
}
}
单链表的使用(插入,查找,删除,链表的倒置,删除相同结点)
时间: 2024-11-05 16:36:46