C语言程序设计(王立柱)第八章答案 链表

简介: 只有聪明人才能看见的摘要~( ̄▽ ̄~)~

 先附一个

node.h

list.h

Josephus.c

#pragma once
//node.h
#include<stdlib.h>
typedef struct Node{
  Type data;
  struct Node* prev;
  struct Node* next;
}Node;
Node* GetNode(Type item, Node* p, Node* n);
Type GetData(Node* itr) { return itr->data; }
Node* GetPrev(Node* itr) { return itr->prev; }
Node* GetNext(Node* itr) { return itr->next; }
Node* GetNode(Type item, Node* p, Node* n) {
  Node* re;
  re = (Node*)malloc(sizeof(Node));
  re->data = item;
  re->prev = p;
  re->next = n;
  return re;
}
#pragma once
//list.h
#include"node.h"
typedef struct {
  Node* head;
  Node* tail;
  int size;
}List;
void InitList(List* l);             //准构造函数,建立空表
int Size(List* l) { return l->size; }
int Empty(List* l) { return l->size == 0; }
//读取区间边界
Node* Begin(List* l) { return l->head->next; }  //读取数据首节点指针
Node* End(List* l) { return l->tail; }      //读取链表尾节点指针
Node* Insert(List* l, Node* itr, Type item);  //定点插入到itr前面
void PushFront(List* l, Type item) { Insert(l, Begin(l), item); }//首插
void PushBack(List* l, Type item) { Insert(l, End(l), item); }//尾插
Node* Erase(List* l, Node* itr);        //删除itr指向的结点,返回后继指针
void PopFront(List* l) { Erase(l, Begin(l)); }  //首删
void PuopBack(List* l) { Erase(l, GetPrev(End(l))); }//尾删
void Clear(List* l) { while (!Empty(l))PopFront(l); }//清表
void FreeList(List* l) { Clear(l); free(l->head); free(l->tail); }//准析构函数
void InitList(List* l) {
  l->head = GetNode(0, NULL, NULL);
  l->tail = GetNode(0, 0, 0);
  l->head->next = l->tail;
  l->tail->prev = l->head;
  l->size = 0;
}
Node* Insert(List* l, Node* itr, Type item) {
  //Node* p = itr;
  itr->prev->next = GetNode(item, itr->prev, itr);
  itr->prev = itr->prev->next;
  l->size++;
  return itr->prev;
}
Node* Erase(List* l, Node* itr) {
  //Node* p = itr;
  Node* re = itr->next;
  itr->prev->next = itr->next;
  itr->next->prev = itr->prev;
  free(itr);
  l->size--;
  return re;
}
//Josephus.c
#include<stdio.h>
#include<time.h>
typedef int Type;
#include"list.h"
void OutputList(List* l);
void Josephus(int n);
int main() {
  int n;
  printf("Enter the number of people:\n");
  scanf("%d", &n);
  Josephus(n);
  return 0;
}
void OutputList(List* l) {
  Node* first = Begin(l);
  Node* last = End(l);
  for (; first != last; first = GetNext(first))
    printf("%d\t", GetData(first));
  printf("\n");
}
void Josephus(int n) {
  int counter;          //计数器
  int step;           //随机步长
  Node* first;
  Node* last;
  List Party;           //参与者
  List Loser;           //淘汰者
  List Odd;           //随机步长
  InitList(&Party);
  InitList(&Loser);
  InitList(&Odd);
  for (counter = 1; counter <= n; counter++)
    PushBack(&Party, counter);  //参赛者输入
  printf("Party:\n");       //参赛者输出
  OutputList(&Party);
  srand(time(0));
  first = Begin(&Party);      //数据首结点
  last = End(&Party);       //链表尾结点
  while (Size(&Party) > 1) 
  {
    step = 1 + rand() % 10;
    PushBack(&Odd, step);
    for (counter = 1; counter < step; counter++) {
      first = GetNext(first);     //计算步数一步步把first移到淘汰者处
      if (first == last)        //把链表尾结点转到数据首结点
        first = Begin(&Party);
    }
    PushBack(&Loser,GetData(first));        //淘汰者入Loser
    first = Erase(&Party, first);   //淘汰者淘汰
    if (first == last)        //把链表尾结点转到数据首结点
      first = Begin(&Party);
  }
  printf("Odds:\n");
  OutputList(&Odd);
  printf("Loser:\n");
  OutputList(&Loser);
  printf("Winner:\n");
  printf("%d\n", *Begin(&Party));
//用 printf 语句来打印结构体类型的变量,结果是 undefined behavior!
//什么是未定义行为,就是说发生任何状况都是可能的,这个就要看编译器的实现方式了。
//当然改成GetData(Begin(&Party))就没问题了。
  FreeList(&Party);
  FreeList(&Loser);
  FreeList(&Odd);
}

image.gif

有两个点需要注意

第一:书上的代码printf("%d\n", *Begin(&Party));这是不严谨的,应该改GetData(Begin(&Party)),虽然结果是对的,但是由于编译器的行为不同,可能出现不同的结果。我找到这个问题的答案来源于blog.csdn.net/weixin_42181686/article/details/117102972?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%A6%82%E6%9E%9Cprintf%E7%9A%84%25d%E5%8D%B4%E6%98%AF%E4%B8%80%E4%B8%AA%E7%BB%93%E6%9E%84%E6%80%8E%E4%B9%88%E5%8A%9E&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-1-.pc_search_download_positive&spm=1018.2226.3001.4187

第二,书上的list的插入和删除函数都新定义了一个Node* p; 来p=itr; 我觉得去掉也没区别,因此这导致了我一上午的折磨,调用GetNext()和Erase()函数时无数次first变成空指针然后访问越界程序异常终止,我人都快折磨疯了又换回书上的代码然后运行成功了,这没什么,关键是我百思不得其解又找不到答案就又改回了自己的代码,然后又每次都成功了,wtm,无话可说

题目:

选择排序和链表复制(只贴源文件,需要的头文件前面已经贴了)

#include<stdio.h>
typedef int Type;
#include"list.h"
void OutputList(const List* l);
void Selection(List* l);
void Copy(const List* lo, List* lt);
Node* MaxOfNode(Node* n);
int main() {
  int n;
  int i;
  List lo;
  List lt;
  InitList(&lo);
  InitList(&lt);
  int temp = 0;
  printf("输入链表长度n和n个整数:\n");
  scanf("%d", &n);
  for (i = 0; i < n; i++) {
    scanf("%d", &temp);
    PushBack(&lo, temp);
  }
  Selection(&lo);
  Copy(&lo, &lt);
  OutputList(&lo);
  OutputList(&lt);
  FreeList(&lo);
  FreeList(&lt);
  return 0;
}
void OutputList(const List* l) {
  Node* first = Begin(l);
  Node* last = End(l);
  for (; first != last; first = GetNext(first))
    printf("%d\t", GetData(first));
  printf("\n");
}
Node* MaxOfNode(Node* n) {
  int i;
  Node* temp = n;
  Node* max = temp;
  while (temp->next->next != 0) {//temp最多为倒数第二个数据结点
    if (GetData(max) < GetData(temp->next))
      max = temp->next;
    temp = temp->next;
  }
  return max;
}
void Selection(List* l) {
  Node* max;
  Node* temp = Begin(l);//temp是从第一个到倒数第二个数据节点的定位标
  while (temp->next->next != 0) {//temp最多为倒数第二个数据结点
    max = MaxOfNode(temp);
    if (max == temp) {
      temp = temp->next;
      PushFront(l, GetData(temp->prev));
      Erase(l, temp->prev);
    }
    else {
      PushFront(l, GetData(max));
      Erase(l, max);
    }
  }
  PushFront(l, GetData(End(l)->prev));
  Erase(l, End(l)->prev);
}
void Copy(const List* lo, List* lt) {
  Node* one = Begin(lo);
  while (one->next != 0) {
    PushBack(lt, GetData(one));
    one = one->next;
  }
}

image.gif


目录
相关文章
|
7天前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
46 16
|
11天前
|
算法 C语言
【C语言程序设计——循环程序设计】求解最大公约数(头歌实践教学平台习题)【合集】
采用欧几里得算法(EuclideanAlgorithm)求解两个正整数的最大公约数。的最大公约数,然后检查最大公约数是否大于1。如果是,就返回1,表示。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。作为新的参数传递进去。这个递归过程会不断进行,直到。有除1以外的公约数;变为0,此时就找到了最大公约数。开始你的任务吧,祝你成功!是否为0,如果是,那么。就是最大公约数,直接返回。
65 18
|
11天前
|
Serverless C语言
【C语言程序设计——循环程序设计】利用循环求数值 x 的平方根(头歌实践教学平台习题)【合集】
根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码,求解出数值x的平方根;运用迭代公式,编写一个循环程序,求解出数值x的平方根。注意:不能直接用平方根公式/函数求解本题!开始你的任务吧,祝你成功!​ 相关知识 求平方根的迭代公式 绝对值函数fabs() 循环语句 一、求平方根的迭代公式 1.原理 在C语言中,求一个数的平方根可以使用牛顿迭代法。对于方程(为要求平方根的数),设是的第n次近似值,牛顿迭代公式为。 其基本思想是从一个初始近似值开始,通过不断迭代这个公式,使得越来越接近。
42 18
|
11天前
|
C语言
【C语言程序设计——循环程序设计】统计海军鸣放礼炮声数量(头歌实践教学平台习题)【合集】
有A、B、C三艘军舰同时开始鸣放礼炮各21响。已知A舰每隔5秒1次,B舰每隔6秒放1次,C舰每隔7秒放1次。编程计算观众总共听到几次礼炮声。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。开始你的任务吧,祝你成功!
43 13
|
6天前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
19 3
|
6天前
|
存储 算法 安全
【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
11 2
|
10天前
|
存储 编译器 C语言
【C语言程序设计——函数】回文数判定(头歌实践教学平台习题)【合集】
算术运算于 C 语言仿若精密 “齿轮组”,驱动着数值处理流程。编写函数求区间[100,500]中所有的回文数,要求每行打印10个数。根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码。如果操作数是浮点数,在 C 语言中是不允许直接进行。的结果是 -1,因为 -7 除以 3 商为 -2,余数为 -1;注意:每一个数据输出格式为 printf("%4d", i);的结果是 1,因为 7 除以 -3 商为 -2,余数为 1。取余运算要求两个操作数必须是整数类型,包括。开始你的任务吧,祝你成功!
41 1
|
7月前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
7月前
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表
|
7月前
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
69 2

热门文章

最新文章