头歌链表7

第7关:编写程序输入n个整数链式存放并输出最大值

  • 任务要求
  • 参考答案
  • 评论3

任务描述

本关任务:编写程序,输入n个整数链式存放并输出最大值。

相关知识

  在计算机中,除了用一组地址连续的存储单元存放数据,还可以用一组地址不连续的存储单元存储数据,这种存放数据的结构,称作链式存储结构。   链式存储结构是一种动态地进行存储分配的数据结构,优点是不需要事先确定最大长度,在插入或者删除元素时,也不会引起数据的大量移动;缺点是只能顺序访问链表中的元素,不能随机存取数据。

  设有4个相同类型的数据ABCD,这4个数据类型可以是数值型、字符串型或自定义的结构体类型,它们的顺序存储结构和链式存储结构的示意图如图 1 所示。

  设计一个单链表的结点结构如下:

  链式存储结构中,每个元素称为一个结点,每个结点都可存储在内存中不同的位置,为了表示每个元素与后继元素之间的逻辑关系,以便构成一个结点链着一个结点的链式存储结构,每个结点都包含两个部分:第 1 部分是数据域,用来存储元素本身的数据信息,这里用data表示;第 2 部分是指针域,用来存储下一个结点的地址,这里用next表示。如此串连下去直到最后一个结点,最后一个结点称为“表尾”,该结点的指针域值为 0,指向内存中编号为零的地址(常用符号常量 NULL 表示,称为空地址),表尾不再有后继结点。

  举例说明,输入3个整数,链式存放,定义链表的结点类型如下:

 
  1. struct Node
  2. {
  3. int data;
  4. struct Node *next;
  5. } ;
  6. typedef struct Node LNode;
  7. typedef struct Node * LinkList;

  data成员用于存放输入的整数,next成员用于存放下一个结点的地址。

  如果结点的类型定义采用如下方法,系统编译能不能通过?

 
  1. struct Node
  2. {
  3. int data;
  4. struct Node next;
  5. };

  系统编译不能通过,结构体声明时不能包含本结构体类型成员,这是因为本结构体类型尚未定义结束,它所占用的内存单元的字节数尚未确定,因此系统无法为这样的结构体成员分配内存。结构体声明时,可以包含本结构体类型的指针成员。   因为指针其实就是地址,与它所指的基类型无关, 只与机器有关。 如果你的机器是16位寻址的,那指针就是16位的,2个字节;如果是32位寻址的,指针也是32位的,4个字节;如果寻址是64位的,指针也是64位,8个字节。

 
  1. /**********创建3个结点存放3个整数 **********/
  2. /**********创建3个结点存放3个整数 **********/
  3. LNode * p1, * p2, * p3;
  4. p1=( LNode *)malloc(sizeof(LNode)); //申请动态内存
  5. if(p1==NULL) //对动态内存分配是否成功进行检测
  6. {
  7. printf("不能成功分配存储空间。\n");
  8. exit(1);
  9. }
  10. scanf("%d",&p1->data); //将输入的整数存放在结点的data域
  11. /**********申请动态内存的同时并且检测**********/
  12. if ( ( p2 = (LNode *)malloc(sizeof(LNode) ) ) == NULL )
  13. {
  14. printf("不能成功分配存储空间。\n");
  15. exit(1);
  16. }
  17. scanf("%d",&p2->data); //将输入的整数存放在结点的data域
  18. if( (p3 = (LNode t *)malloc(sizeof(LNode)) ) == NULL)
  19. {
  20. printf("不能成功分配存储空间。\n");
  21. exit(1);
  22. }
  23. scanf("%d", &p3->data ); //将输入的整数存放在结点的data域
  24. /**********将3个结点连接起来 **********/
  25. p1->next = p2; //将p2链接在p1后
  26. p2->next = p3; //将p3链接在p2后
  27. p3->next = NULL; // p3后没有结点

  结点链接后通过p1,能找到p2,通过p2,能找到p3p2p3的值不重要了,重要的是p1的值不能丢。改进上述操作,用循环语句来完成建立链表:

 
  1. /**********循环建立3个结点的链表**********/
  2. LNode * p1, * p2, *head;
  3. if ( ( p1 = (LNode *)malloc(sizeof(LNode) ) ) == NULL ) //创建第1个结点
  4. {
  5. printf("不能成功分配存储空间。\n");
  6. exit(1);
  7. }
  8. scanf("%d",&p1->data);
  9. head = p1;
  10. for(i=1;i<3;i++) //循环创建其余结点
  11. {
  12. if ( ( p2 = (LNode *)malloc(sizeof(LNode) ) ) == NULL )
  13. {
  14. printf("不能成功分配存储空间。\n");
  15. exit(1);
  16. }
  17. scanf("%d",&p2->data);
  18. p1->next = p2;
  19. p1 = p2;
  20. }
  21. p2->next=NULL; //将链表最后一个结点指针域置为空值
  22. }

  如果希望将第1个结点的创建也在循环语句里进行,可以在第1个结点之前附设一个头结点,单链表有带头结点和不带头结点之分:

  在链表的开始结点之前附加一个结点,并称它为头结点,头结点的数据成员不用来存放数据,那么会带来以下两个优点:

  • 由于存放第一个数据元素结点的位置被存放在头结点的指针域中,所以在链表的第一个位置上的操作就和在表的其它位置上的操作一致,无需进行特殊处理;
  • 无论链表是否为空,其头指针是指向头结点的非空指针,空表中头结点的指针域为空,因此空表和非空表的处理也就统一了。
 
  1. LNode * p1, * p2, *head;
  2. if ( ( head = (LNode *)malloc(sizeof(LNode) ) ) == NULL ) //创建头结点
  3. {
  4. printf("不能成功分配存储空间。\n");
  5. exit(1);
  6. }
  7. p1 = head;
  8. for(i=0; i<3; i++) //循环创建其余结点
  9. {
  10. if ( ( p2 = (LNode *)malloc(sizeof(LNode) ) ) == NULL )
  11. {
  12. printf("不能成功分配存储空间。\n");
  13. exit(1);
  14. }
  15. scanf("%d",&p2->data);
  16. p1->next = p2;
  17. p1 = p2; //p1始终指向链表最后一个结点
  18. }
  19. p2->next=NULL; //将链表最后一个结点指针域置为空值
  20. }

  上述创建单链表的方法称为尾插法,将建立单链表的操作模块化,定义创建带头结点的单链表的函数:

 
  1. void CreateTailList(LinkList L, int n)
  2. {
  3. LNode *p,* tail;
  4. int i,x;
  5. tail = L; //设置尾指针,方便插入
  6. for(i=0; i<n; i++) //循环创建其余结点
  7. {
  8. if ( ( p = (LNode *)malloc(sizeof(LNode) ) ) == NULL )
  9. {
  10. printf("不能成功分配存储空间。\n");
  11. exit(1);
  12. }
  13. scanf("%d",&p->data);
  14. tail ->next = p;
  15. tail = p; //p1始终指向链表最后一个结点
  16. }
  17. p->next=NULL; //将链表最后一个结点指针域置为空值
  18. }

  请模仿单链表的创建函数定义,输出单链表的函数及销毁带头结点的单链表的函数。

编程要求

根据提示,在右侧编辑器 Begin-End 区间补充代码,完成子函数的自定义,实现输入n个整数链式存放并输出最大值。

测试说明

平台会对你编写的代码进行测试。

测试输入: 4 64 25 17 83

输入说明: 第一个数字为整数个数; 第一个数字后面的数字为整数的具体值。

预期输出: max=83


开始你的任务吧,祝你成功!

#include<stdio.h>
#include<stdlib.h>
struct Node//定义链表的结点类型
{
    int data;
    struct Node *next;
} ;
typedef  struct Node   LNode;  
typedef  struct Node  * LinkList;  
void CreateTailList (LinkList  L,int n);   
void OutputList(LinkList L);       //输出带头结点的单链表
void DestroyList(LinkList  L);    //销毁带头结点的单链表
int MaxList(LinkList  L);        //求带头结点的单链表最大值
 
int main()
{
    LinkList  head;          //定义一个LinkList 型的变量head
    int n;
    if( ( head = (LNode *) malloc( sizeof(LNode) ) ) == NULL)  
    {  
        printf("申请空间失败!");  
        exit(0);  
    }  
    head ->next=NULL;      //在函数体外创建单链表的头结点head
    scanf("%d",&n);
    CreateTailList ( head,n);     //用尾插法输入数据创建单链表
    //OutputList(head);         //输出以head为头的链表各结点的值
    printf("max=%d\n", MaxList(head) );
    DestroyList (head);        //销毁以head为头的链表各结点
}
/********** 定义CreateTailList()函数 **********/ 
/********** Begin **********/ 
void CreateTailList( LinkList L,int n)
{
    LNode *p,*tail;
    int i,x;
    tail=L;
    for(i=0;i<n;i++)
    {
        p=(LNode*)malloc(sizeof(LNode));
        scanf("%d",&p->data);
        tail->next=p;
        tail=p;
    }
    p->next=NULL;
}
/********** End **********/
/**********定义DestroyList()函数**********/ 
void  DestroyList (LinkList  head) 
{
/********* Begin **********/ 
free(head);
/********** End **********/
}
/**********定义MaxList ()函数**********/ 
int MaxList(LinkList  L)
{  
/********** Begin **********/
  int max=0;
  LNode *p; 
  p=L->next;
   while(L)
 {
      L=L->next;
     if(max<p->data)
     max=p->data;
      p=L;
 }
 return max;
 /********** End **********/
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
单向链表排序可以通过不同的排序算法来实现,比如冒泡排序、插入排序、选择排序、归并排序和快速排序等。下面以冒泡排序为例进行说明。 冒泡排序是一种简单的排序算法,它重复地遍历链表,并通过两个相邻节点的比较来交换节点的位置,直到整个链表有序为止。具体实现步骤如下: 1. 设置两个指针,一个指向链表的头节点,另一个指向头节点的下一个节点。 2. 遍历链表,比较当前节点和下一个节点的值,如果需要交换位置则交换。 3. 继续遍历链表,直到指针指向链表的尾节点。 4. 如果有任何节点交换了位置,则重新开始遍历链表,直到没有节点需要交换位置为止。 5. 链表排序完成。 下面是使用C语言实现的单向链表排序代码: ```c #include <stdio.h> // 定义链表节点结构 struct ListNode { int val; struct ListNode *next; }; // 冒泡排序函数 void bubbleSort(struct ListNode *head) { if (head == NULL || head->next == NULL) { return; } int swapped; struct ListNode *ptr1; struct ListNode *lptr = NULL; do { swapped = 0; ptr1 = head; while (ptr1->next != lptr) { if (ptr1->val > ptr1->next->val) { // 交换节点位置 int tmp = ptr1->val; ptr1->val = ptr1->next->val; ptr1->next->val = tmp; swapped = 1; } ptr1 = ptr1->next; } lptr = ptr1; } while (swapped); } // 测试用例 int main() { // 创建链表 struct ListNode n1, n2, n3, n4; n1.val = 4; n2.val = 2; n3.val = 1; n4.val = 3; n1.next = &n2; n2.next = &n3; n3.next = &n4; n4.next = NULL; // 排序链表 bubbleSort(&n1); // 输出排序结果 struct ListNode *ptr = &n1; while (ptr != NULL) { printf("%d ", ptr->val); ptr = ptr->next; } return 0; } ``` 以上代码中,我们首先定义了一个链表节点结构 `struct ListNode`,包含一个整数值 `val` 和一个指向下一个节点的指针 `next`。然后我们使用冒泡排序算法实现了 `bubbleSort` 函数,最后在 `main` 函数中创建了一个测试用例并进行排序输出。输出结果为 `1 2 3 4`,表示链表已经按照从小到大的顺序进行了排序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值