找到链表的中间节点
使用快慢指针,从头结点开始,快指针每次往后移动两个,慢指针一个。
当快指针指向链表尾时,链表的长度为奇数,慢指针指向的就是中间节点。
当快指针指向NULL时,链表的长度为偶数,慢指针指向的结点,以及该节点的前一个结点就是中间节点。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct student {
int num;
float score;
struct student* pNext;//指向下一个结点的指针
}stu, * pstu;
//我们建立的链表是不带头结点的
//有序插入法
void list_sort_insert(pstu* pphead, pstu* pptail, int i)
{
pstu pnew = (pstu)calloc(1, sizeof(stu));
pnew->num = i;
pstu ppre = *pphead;
pstu pcur = *pphead;
//判断链表是否为空
if (NULL == *pphead)
{
*pphead = pnew;
*pptail = pnew;
}
else if (i < pcur->num)//如果i的值小于链表头的值,使用头插法插入i,作为新的链表头
{
pnew->pNext = *pphead;
*pphead = pnew;
}
else {//遍历链表,找到位置,插入到链表中间
while (pcur)
{
if (i < pcur->num)
{
ppre->pNext = pnew;
pnew->pNext = pcur;
break;
}
ppre = pcur;
pcur = pcur->pNext;
}
//一直遍历到了最后一个,都比i小,那就用尾插法把i放到最后
if (NULL == pcur)
{
(*pptail)->pNext = pnew;
*pptail = pnew;
}
}
}
//链表打印
void list_print(pstu phead)
{
while (phead)
{
printf("%3d", phead->num);
phead = phead->pNext;
}
printf("\n");
}
//链表长度
int list_len(pstu phead, pstu ptail)
{
int i = 0;
while (phead)
{
i++;
phead = phead->pNext;
}
return i;
}
//找出链表中间节点
void list_middle(pstu phead, pstu ptail, int* p_1, int* p_2)
{
pstu fast = phead;//快指针
pstu slow = phead;//满指针
pstu ppre = phead;//指向快指针的前一个结点
while (fast != NULL && fast != ptail)
{
fast = fast->pNext->pNext;
ppre = slow;
slow = slow->pNext;
}
if (fast == ptail)
{
*p_2 = slow->num;
}
else {
*p_1 = ppre->num;
*p_2 = slow->num;
}
}
int main()
{
//首先定义两个结构体指针?一个指向链表头,一个指向链表尾?
pstu phead = NULL, ptail = NULL;
int i;//用i存读入、要输入的数
while (scanf("%d", &i) != EOF)//循环读取,scanf返回值是读入的数据的个数
{
//list_head_insert(&phead, &ptail, i);
//list_tail_insret(&phead, &ptail, i);
list_sort_insert(&phead, &ptail, i);
}
list_print(phead);
int len = 0, ret_1 = 0,ret_2 = 0;
len = list_len(phead, ptail);//统计链表长度
list_middle(phead, ptail, &ret_1, &ret_2);//找出链表中间节点
if (1 == len % 2)
{
printf("链表的中间节点是:%d\n", ret_2);
}
else {
printf("链表的中间节点是:%d %d\n", ret_1, ret_2);
}
return 0;
}