【数据结构】通过一趟遍历确定长度为n的单链表中值最大的节点(用C语言实现)

此题为课本p51页,算法题第6题

目录

一、定义结构体

二、用尾插法创建单链表

三、遍历单链表,找出最大的值得节点得位置,并输出该节点保存得数据

四、设计一下,实现一下这个遍历和输出最大的节点

五、完整代码

六、运行测试一下


一、定义结构体

typedef struct LNode
{
    int data;
    struct LNode* next;
} LNode;

二、用尾插法创建单链表

LNode* CreateAtTail(int a[], int n)
{
    int i;
    LNode* first, * s, * r;
    first = (LNode*)malloc(sizeof(LNode));
    first->next = NULL;
    r = first;
    for (i = 0; i < 5; i++)
    {
        s = (LNode*)malloc(sizeof(LNode));
        s->data = a[i];
        r->next = s;
        r = s;
    }
    r->next = NULL;
    return first;
}

三、遍历单链表,找出最大的值得节点得位置,并输出该节点保存得数据

void COMList(LNode* first)
{
    LNode *p;
    int max = 0;
    int count = 1;
    int i = 0;
    int biaoji = 1;
    p = first->next;
    max = p->data;
    while (p != NULL)
    {
        i++;
        if (p->data > max)
        {
            max = p->data;
            count = count + i - biaoji;
            biaoji = i;
        }  
        p = p->next;
    }
    printf("单链表中值最大的节点为第 %d 个值为 %d ", count, max);
}

 还有就是p=p->next为什么放到if条件句下面,如果放到,上面的话,比较到最后,p成为了NULL,而这时,再用p->data和max比较时,就没有这个节点了,怎么比较。

还有我这个代码,其实把第一个元素也比较了一遍,其实这一步没有必要,因为肯定不会比初始max,也就是第一个本身大吧。(但是目前我没想出来怎么改)

yes!

想到了

代码如下,就是把循环条件改了一下(这里不改的话,只改if的话,p->next又会出现上面空指针的情况),if条件句的条件改了一下,max的值改了一下。大家可以理解一下。

不会的留言问我呀~

void COMList(LNode* first)
{
    LNode *p;
    int max = 0;
    int count = 1;
    int i = 1;
    int biaoji = 1;
    p = first->next;
    max = p->data;
    while (p->next != NULL)
    {
        i++;
        if (p->next->data > max)
        {
            max = p->next->data;
            count = count + i - biaoji;
            biaoji = i;
        }
        
        p = p->next;
    }
    printf("单链表中值最大的节点为第 %d 个值为 %d ", count, max);
}

其中这里还有比较难理解的一点就是那个count的运算:

常见的错误就是,直接count++,这样的算出来的结果肯定是不对的,就比如输入五个数(这里我测试的是链表长度为5,都为整型),1 3 2 5 4,这里,if条件句,会把2隔过去,这样count就会少加1,等等,类似的情况,看表长和表的数据,少加2,3....等等。

正解就是,用i来记录比较到第几个数,再用biaoji这个变量记录上次p->data大于max的情况时的第biaoji个位置,再用i-biaoji加到count上即可,比如,上个例子,1 3 2 5 4,3的位置为2,5的位置为4,这样4-2=2,count+2即可,就不会少加一个,把位置给算错了。

再举一个例子比如,1 2 2 2 5,第一次进入时是第一个2的位置为2,第2个2,第三个2都进不去,到5,位置为5,相差5-2=3,这样count+3就行了,就不会少加了。

如果不理解,再举一个例子,1 2 3 4 5,1进不去,第一个进入的是2,位置为2,3进去,位置为3,count+3-2,就是count+1就行了。

四、设计一下,实现一下这个遍历和输出最大的节点

int main()
{
    LNode* first;
    int a[5];
    int i = 0;
    int count = 0;
    printf("请输入5个数,进行初始化链表:\n");
    for (i = 0; i < 5; i++)
    {
        scanf_s("%d", &a[i]);
    }
    first = CreateAtTail(a, 5);
    COMList(first);
    return 0;
}

五、完整代码

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

typedef struct LNode
{
    int data;
    struct LNode* next;
} LNode;


void COMList(LNode* first)
{
    LNode *p;
    int max = 0;
    int count = 1;
    int i = 0;
    int biaoji = 1;
    p = first->next;
    max = p->data;
    while (p != NULL)
    {
        i++;
        if (p->data > max)
        {
            max = p->data;
            count = count + i - biaoji;
            biaoji = i;
        }
        
        p = p->next;
    }
    printf("单链表中值最大的节点为第 %d 个值为 %d ", count, max);
}
LNode* CreateAtTail(int a[], int n)
{
    int i;
    LNode* first, * s, * r;
    first = (LNode*)malloc(sizeof(LNode));
    first->next = NULL;
    r = first;
    for (i = 0; i < 5; i++)
    {
        s = (LNode*)malloc(sizeof(LNode));
        s->data = a[i];
        r->next = s;
        r = s;
    }
    r->next = NULL;
    return first;
}
int main()
{
    LNode* first;
    int a[5];
    int i = 0;
    int count = 0;
    printf("请输入5个数,进行初始化链表:\n");
    for (i = 0; i < 5; i++)
    {
        scanf_s("%d", &a[i]);
    }
    first = CreateAtTail(a, 5);
    COMList(first);
    return 0;
}

六、运行测试一下

 

 

 有错误请指正~

不会的不理解的评论留言问我呀~

大家快去试一下这个代码!

猜你喜欢

转载自blog.csdn.net/m0_57549888/article/details/124434196