题目要求:
创建一个长度为n的链表,然后删除链表的倒数第x个结点,
并输出删除操作后的链表。
输入样例:
5 2
1 2 3 4 5
输出样例:
1>2->3->5
方法一:
普通链表删除操作实现:这种方法相对简单一些,主要是找到倒数第x结点的位置,然后执行删除操作,具体实现如下 :
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}Node,*Link;
Link create(); //创建头一个带头结点的单链表
void rear(Link head,int num); //尾插法把数插入链表
void delete_(Link head,int save); // 删除指定节点
void display(Link head); //显示链表
int main()
{
Link head = create(); //设置头结点
int n,x,i,save,num;
scanf("%d %d",&n,&x);
for(i = 0;i < n;i++)
{
scanf("%d",&num);
if(i == n - x) //倒数第x就是正数第n - x(下标)
{
save = num;
}
rear(head,num); //将数字依次插入链表中
}
delete_(head,save); //删除倒数第x结点
display(head); //显示链表
return 0;
}
Link create()
{
Link head = NULL;
head = (Link)malloc(sizeof(Node));
if(head == NULL)
{
printf("error");
return NULL;
}
head->data = 0; //初始化头节点
head->next = NULL;
return head;
}
void rear(Link head,int num)
{
Link p = head;
Link pr = NULL; //pr为新节点,需要动态内存分配
pr = (Link)malloc(sizeof(Node));
if(pr == NULL)
{
printf("error");
return ;
}
pr->data = num; //将num的值 赋给新节点
if(head->next == NULL) //头节点指向的下一个为空,可以直接插进去
{
head->next = pr;
pr->next = NULL; //插进去之后,这个新节点指向的下一个就是空
}
else
{
while(p->next != NULL) //遍历整个链表,注意循环条件是p->next不为空
{
p = p->next;
}
p->next = pr; //遍历到最后一个退出循环,然后插入新节点
pr->next = NULL;
}
return ;
}
void delete_(Link head,int save)
{
Link p,pr; //设置一前一后两个节点
p = head;
pr = head->next;
if(head == NULL)
{
printf("error");
return ;
}
while(pr->data != save && pr->next != NULL) //不是要删除的数,指向的下一个也不为空,进入循环
{
p = pr; //每一次前面存后面
pr = pr->next; //继续往下遍历
}
if(pr->data == save) //找到了
{
if(pr == head) //特殊情况优先考虑 :恰好是头结点,直接删
{
head->next = pr->next;
}
else
{
p->next = pr->next;
}
free(pr); //记得释放删除的结点
}
return ;
}
void display(Link head)
{
Link pr = head->next;
while(pr != NULL)
{
if(pr->next != NULL) //注意打印格式,如果下一个不是空,就要打印->
{
printf("%d->",pr->data);
}
else
{
printf("%d",pr->data);
}
pr = pr->next; //继续往下遍历
}
return ;
}
运行结果:
方法二:
通过快慢指针来实现,快慢指着查找删除结点所在的位置,快指针比慢指针多走 x 步,快指针先走了 x 步再让慢指针开始走,两指针一起走,最后返回慢指针,则是删除节点的位置。具体实现如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}Node,*Link;
Link create(); //创建头结点
void rear(Link head,int num); //尾插法插入新节点 (插入n个num)
Link find(Link head,int x); //快慢指针来进行删除操作
void display(Link head); //显示链表
int main()
{
Link head = create();
int n,i,x,num; //输入n 和 倒数第x结点
scanf("%d %d",&n,&x);
for(i = 0;i < n;i++)
{
scanf("%d",&num); //录入每个数
rear(head,num); //插入链表
}
display(find(head,x)); //陈列
return 0;
}
Link create() //创建头节点
{
Link head = NULL;
head = (Link)malloc(sizeof(Node));
if(head == NULL)
{
printf("分配失败!");
return NULL;
}
head->data = 0;
head->next = NULL;
return head;
}
void rear(Link head,int num) //尾插法插入
{
Link p = NULL,pr = NULL;
p = head;
pr = NULL;
pr = (Link)malloc(sizeof(Node));
if(pr == NULL)
{
printf("分配失败!");
}
pr->data = num; //data域赋值
if(head->next == NULL) //只有头结点,直接插入
{
head->next = pr;
pr->next = NULL;
}
else //否则,遍历到最后 然后插入
{
while(p->next != NULL)
{
p = p->next;
}
p->next = pr;
pr->next = NULL;
}
return ;
}
Link find(Link head,int x) //快慢指针查找操作,找到删除结点的位置
{
if(head == NULL || x <= 0)
{
return NULL;
}
Link fast = head,slow = head; //设一个快慢指针,快指针比慢指针先走n步
while(fast != NULL && x > 0) //快指针先走x步
{
fast = fast->next;
x--;
}
while(fast->next != NULL) //慢指针开始走 ,注意条件未快指针指向不为空
{
slow = slow->next;
fast = fast->next;
}
if(slow->next != NULL) //快指针走完,剩下慢指针继续遍历
{
slow->next = slow->next->next;
}
return head;
}
void display(Link head)
{
Link pr = head->next;
while(pr != NULL)
{
if(pr->next != NULL) //注意输出格式
{
printf("%d->",pr->data);
}
else
{
printf("%d",pr->data);
}
pr = pr->next;
}
return ;
}
运行结果: