Files
Fortran-95-2003-Program-3rd…/20210525-第15章习题.f90
2025-09-25 16:46:47 +08:00

1016 lines
50 KiB
Fortran
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

! ==============================================================================
! 通过 gfortran ./test.f90 -o ./run && ./run 运行
! 程序名:
! 第15章习题
! 目的:
!
! 修订记录:
! 日期 编程者 改动描述
! =================== ============= =====================================
! 2021-05-25 15:25:35 Sola 习题15-1 ~ 习题15-2 跳过
! 2021-05-25 15:28:00 Sola 习题15-3 指向非同类型地址以及赋值操作空格测试
! 2021-05-25 15:35:37 Sola 习题15-4 跳过
! 2021-05-25 15:35:50 Sola 习题15-5 测试未定义的ASSOCIATED值
! 2021-05-25 15:42:41 Sola 习题15-6 跳过
! 2021-05-25 15:42:53 Sola 习题15-7 指向数组及数组元素的指针
! 2021-05-25 15:53:19 Sola 习题15-8 指向数组的指针的上下界
! 2021-05-25 16:24:28 Sola 习题15-7 ~ 习题15-10 跳过
! 2021-05-25 16:24:56 Sola 习题15-11 测试子程序中指针的分配
! 2021-05-25 16:41:56 Sola 习题15-12 跳过
! 2021-05-25 16:42:06 Sola 习题15-13 插入排序程序(链表)
! 2021-05-25 19:19:01 Sola 习题15-14 插入排序程序(二叉树)
! 2021-05-26 04:39:20 Sola 习题15-15 ~ 习题15-16 跳过
! 2021-05-26 04:41:43 Sola 习题15-17 返回数组最大值指针
! 2021-05-26 11:45:56 Sola 习题15-18 返回数组类型指针最大值指针
! 2021-05-26 11:52:23 Sola 习题15-19 线性最小二乘拟合
! 2021-05-26 17:44:42 Sola 习题15-20 双向链表
! 程序结构:
!
! ==============================================================================
! 主程序:
program Chapter15
implicit none
! 数据字典
! 声明常量
! 声明变量
! 变量初始化
! 数据输入
! 运算过程
! 结果输出
! call Test15_1
! call Exercises15_3
! call Exercises15_5
! call Exercises15_7
! call Exercises15_8
! call Exercises15_11
! call Exercises15_13
! call Exercises15_14
! call Exercises15_17
! call Exercises15_18
! call Exercises15_19
! call Exercises15_20
! call Exercises15_21
! call Test
! call Exercises15_22
call Exercises15_21new
end program Chapter15
! ==============================================================================
! 习题15-3 指向非同类型地址以及赋值操作空格测试
subroutine Exercises15_3
implicit none
real, pointer :: p1
real, target :: x1=11.
integer, pointer :: p2
integer, target :: x2=12
p1=>x1
p2 => x2
write(*, '(A, 4G8.2)') ' p1, p2, x1, x2 = ', p1, p2, x1, x2
! p1=>p2
! p2=>x1
! write(*, '(A, 4G8.2)') ' p1, p2, x1, x2 = ', p1, p2, x1, x2
end subroutine Exercises15_3
! 习题15-5 测试未定义的ASSOCIATED值未定义的值还真是随机的。。。
subroutine Exercises15_5
implicit none
real, pointer :: p1, p2
real, target :: x1=11.1, x2=-3.2
p1 => x1
write(*, *) associated(p1), associated(p2), associated(p1, x2)
end subroutine Exercises15_5
! 习题15-7 指向数组及数组元素的指针
subroutine Exercises15_7
implicit none
integer, dimension(:), pointer :: p1 => null()
integer, pointer :: p2 => null()
integer, dimension(1000), target :: array=1
p1 => array
p2 => array(10)
write(*, '(100I1)') p1
write(*, *) p2
end subroutine Exercises15_7
! 习题15-8 指向数组的指针的上下界
subroutine Exercises15_8
implicit none
integer :: i
real, dimension(-25: 25), target :: info=(/ (2.1*i, i = -25, 25) /)
real, dimension(:), pointer :: ptr1, ptr2, ptr3, ptr4
ptr4 => info
ptr1 => info(-25: 25: 5)
ptr2 => ptr1(1:: 2)
ptr3 => ptr2(3: 5)
write(*, '(A, 11F6.1)') ' ptr1 = ', ptr1
! write(*, *) lbound(ptr4), ubound(ptr4)
write(*, '(A, 11F6.1)') ' ptr2 = ', ptr2
write(*, '(A, 11F6.1)') ' ptr3 = ', ptr3
write(*, '(A, 11F6.1)') ' ave of ptr3 = ', sum(ptr3)/size(ptr3)
end subroutine Exercises15_8
! 习题15-11 测试子程序中指针的分配
module my_sub
implicit none
contains
subroutine running_sum(sum, value)
implicit none
real, pointer :: sum, value
! allocate(sum)
sum = sum + value
end subroutine running_sum
end module my_sub
subroutine Exercises15_11
use my_sub
implicit none
integer :: istat
real, pointer :: sum, value
allocate(sum, value, stat=istat)
write(*, *) 'Enter values to add: '
do
read (*, *, iostat=istat) value
if ( istat /= 0 ) exit
call running_sum(sum, value)
write(*, *) ' The sum is ', sum
end do
! contains
! subroutine running_sum(sum, value)
! implicit none
! real, pointer :: sum, value
! ! allocate(sum, value)
! sum = sum + value
! end subroutine running_sum
end subroutine Exercises15_11
! 习题15-13 插入排序程序(链表)
module Linked_List
implicit none
private ! 数据隐藏
public :: linkedList, LinkedListAdd, ShowLinkedList, strLength ! 显示指定数据
integer, parameter :: strLength=12 ! 声明字符串基本长度
type :: linkedList ! 链表结点数据类型
character(len=strLength) :: value ! 结点值
type(linkedList), pointer :: next ! 下一个结点地址
end type linkedList
contains
! recursive subroutine LinkedListAdd(value, ptr) ! 向链表中添加结点
! implicit none
! character(len=strLength), intent(in) :: value ! 声明输入数据
! type(linkedList), pointer, intent(inout) :: ptr ! 声明当前检测的结点
! type(linkedList), pointer :: temp => null() ! 声明临时结点
! if ( .not. associated(ptr) ) then ! 如果检测结点不存在
! allocate(ptr) ! 创建一个新结点
! ptr%value = value ! 该结点的值为输入数据
! ptr%next => null() ! 该节点的下一个结点为空
! else ! 如果检测结点存在
! if ( LGT(Ucase(value), Ucase(ptr%value)) ) then ! 如果输入数据大于结点值
! call LinkedListAdd(value, ptr%next) ! 递归调用
! else ! 如果输入数据小于结点值
! allocate(temp) ! 给temp分配内存
! temp%value = value ! 定义temp值
! temp%next => ptr ! 定义temp下一个结点为当前结点
! ptr => temp ! 将当前结点指针指向temp, 完成结点插入
! end if
! end if
! end subroutine LinkedListAdd
recursive subroutine LinkedListAdd(newNode, ptr) ! 向链表中添加结点
implicit none
type(linkedList), pointer, intent(inout) :: newNode ! 声明插入结点
type(linkedList), pointer, intent(inout) :: ptr ! 声明当前检测的结点
if ( .not. associated(ptr) ) then ! 如果检测结点不存在
ptr => newNode
else ! 如果检测结点存在
if ( LGT(Ucase(newNode%value), Ucase(ptr%value)) ) then ! 如果输入数据大于结点值
call LinkedListAdd(newNode, ptr%next) ! 递归调用
else ! 如果输入数据小于结点值
newNode%next => ptr ! 定义插入结点下一个结点为当前结点
ptr => newNode ! 将当前结点指针指向插入结点
end if
end if
end subroutine LinkedListAdd
recursive subroutine ShowLinkedList(head)
implicit none
type(linkedList), pointer, intent(in) :: head ! 声明输入结点
if ( associated(head%next) ) then ! 如果下一个结点存在
write(*, '(1X, 2A)', advance='no') trim(head%value), ',' ! 输出结果
call ShowLinkedList(head%next) ! 递归调用
else ! 如果下一个结点不存在
write(*, '(1X, A)', advance='yes') trim(head%value) ! 输出结果
end if
end subroutine ShowLinkedList
function Ucase(str)
character(len=*), intent(in) :: str ! 声明输入字符串
character(len=len(str)) :: ucase ! 声明函数类型
integer :: i ! 循环参数
do i = 1, len(str) ! 对输入每个字符循环
if ( lge(str(i: i), 'a') .and. lle(str(i: i), 'z') ) then ! 如果字符在a~z中
Ucase(i: i) = achar( iachar(str(i: i)) - 32 ) ! 输出大写
else
Ucase(i: i) = str(i: i) ! 如果不在, 输出原字符
end if
end do
end function Ucase
end module Linked_List
subroutine Exercises15_13
use Linked_List, only: linkedList, LinkedListAdd, ShowLinkedList, strLength
implicit none
character(len=strLength) :: inputValue ! 声明输入
integer :: errorLevel ! 声明错误状态值
integer :: i=0 ! 循环参数
type(linkedList), pointer :: head => null() ! 声明链表头
type(linkedList), pointer :: newNode => null() ! 声明插入结点
write(*, *) 'Please enter 5 string, the max length is', strLength ! 提示信息
do i = 1, 5 ! 输入五个数据
write(*, '(1X, A)', advance='no') 'Please enter the value: ' ! 提示信息
read(*, *, iostat=errorLevel) inputValue ! 读取输入信息
if ( errorLevel /= 0 ) stop "" ! 检测读取状态
allocate(newNode, stat=errorLevel) ! 分配插入结点内存
if ( errorLevel /= 0 ) stop "" ! 检测分配状态
newNode%value = inputValue ! 给结点赋值
newNode%next => null() ! 定义结点指向地址为空
call LinkedListAdd(newNode, head) ! 插入结点
end do
write(*, '(1X, A)') 'Input ending, show the result:' ! 提示信息
call ShowLinkedList(head) ! 打印链表(截尾)
end subroutine Exercises15_13
! 习题15-14 插入排序程序(二叉树)
! 模块-二叉树
module Binary_Tree
implicit none
private
public :: binaryTreeName, BinaryTreeNameAdd, BinaryTreeNamePrint
type :: binaryTreeName ! 二叉树结点类型数据
real :: var1 ! 二叉树结点值
type(binaryTreeName), pointer :: before ! 该节点前一个结点
type(binaryTreeName), pointer :: next ! 该结点后一个结点
end type binaryTreeName
interface operator(>)
module procedure BinaryTreeNameGreater ! 结点大于比较
end interface
interface operator(<)
module procedure BinaryTreeNameLess ! 结点小于比较
end interface
contains
function BinaryTreeNameGreater(input1, input2) result(result) ! 结点大于比较函数
implicit none
logical :: result ! 输出结果类为布尔
type(binaryTreeName), intent(in) :: input1, input2 ! 输入两个二叉树结点
if ( input1%var1 > input2%var1 ) then
result = .TRUE. ! 如果结点1大于结点2, 则返回TURE
else
result = .FALSE. ! 如果结点1不大于结点2, 返回FALSE
end if
end function BinaryTreeNameGreater
function BinaryTreeNameLess(input1, input2) result(result) ! 结点小于比较函数
implicit none
logical :: result ! 输出结果类为布尔
type(binaryTreeName), intent(in) :: input1, input2 ! 输入两个二叉树结点
if ( input1%var1 < input2%var1 ) then
result = .TRUE. ! 如果结点1小于结点2, 则返回TURE
else
result = .FALSE. ! 如果结点1不小于结点2, 则返回FALSE
end if
end function BinaryTreeNameLess
recursive subroutine BinaryTreeNameAdd(newNode, ptr) ! 向二叉树中添加结点
implicit none
type(binaryTreeName), pointer, intent(inout) :: ptr ! 声明当前检测的结点
type(binaryTreeName), pointer, intent(inout) :: newNode ! 声明临时结点
if ( .not. associated(ptr) ) then ! 如果检测结点不存在
ptr => newNode ! 则将检测结点指向新节点
else ! 如果检测结点存在
if ( newNode > ptr ) then ! 如果输入数据大于结点值
call BinaryTreeNameAdd(newNode, ptr%next) ! 对检测结点后一个递归调用
else ! 如果输入数据小于结点值
call BinaryTreeNameAdd(newNode, ptr%before) ! 对检测结点前一个递归调用
end if
end if
end subroutine BinaryTreeNameAdd
recursive subroutine BinaryTreeNamePrint(root) ! 由小到大打印当前根结点下的所有值
implicit none
type(binaryTreeName), pointer, intent(in) :: root ! 输入指针root
if ( .not. associated(root) ) then
stop "" ! 如果该指针未关联, 停止并报错
else ! 如果该指针已关联
if ( associated(root%before) ) then
call BinaryTreeNamePrint(root%before) ! 如果该指针前一结点存在, 对前一结点递归调用
end if
write(*, '(1X, F10.8)') root%var1 ! 输出当前结点的值
if ( associated(root%next) ) then
call BinaryTreeNamePrint(root%next) ! 如果该指针后一结点存在, 对后一结点递归调用
end if
end if
end subroutine BinaryTreeNamePrint
end module Binary_Tree
! 模块-链表
module Linked_List_real
implicit none
private ! 数据隐藏
public :: linkedList, LinkedListAdd ! 显示指定数据
type :: linkedList ! 链表结点数据类型
real :: value ! 结点值
type(linkedList), pointer :: next ! 下一个结点地址
end type linkedList
contains
recursive subroutine LinkedListAdd(newNode, ptr) ! 向链表中添加结点
implicit none
type(linkedList), pointer, intent(inout) :: newNode ! 声明插入结点
type(linkedList), pointer, intent(inout) :: ptr ! 声明当前检测的结点
if ( .not. associated(ptr) ) then ! 如果检测结点不存在
ptr => newNode ! 则将检测结点指向新节点
else ! 如果检测结点存在
if ( newNode%value > ptr%value ) then ! 如果输入数据大于结点值
call LinkedListAdd(newNode, ptr%next) ! 递归调用
else ! 如果输入数据小于结点值
newNode%next => ptr ! 定义插入结点下一个结点为当前结点
ptr => newNode ! 将当前结点指针指向插入结点
end if
end if
end subroutine LinkedListAdd
end module Linked_List_real
module ModTimePast
implicit none
private
public :: set_timer, elapsed_time
integer, parameter :: sgl=selected_real_kind(p=1) ! 单精度类型数
integer, dimension(8) :: timeNow ! 计算时间用
integer, dimension(8) :: timeOld ! 计算时间用
contains
subroutine set_timer ! 创建子程序1
call DATE_AND_TIME(values=timeNow) ! 调用当前时间子程序
! write(*, *) timeNow
end subroutine set_timer ! 结束子程序1
subroutine elapsed_time(timePast) ! 创建子程序2
real, intent(out) :: timePast ! 定义输出变量
timeOld = timeNow ! 传递值
call set_timer ! 调用子程序1
timePast = ((real(timeNow(3)-timeOld(3))*24 + real(timeNow(5)-timeOld(5)))&
&*60 + real(timeNow(6)-timeOld(6)))*60 + real(timeNow(7)-timeOld(7)) + &
&real(timeNow(8)-timeOld(8))/1000 ! 计算经历时间(秒)
end subroutine elapsed_time ! 结束子程序2
end module ModTimePast
subroutine Exercises15_14
use Binary_Tree, only: binaryTreeName, BinaryTreeNameAdd, BinaryTreeNamePrint
use Linked_List_real, only: linkedList, LinkedListAdd
use ModTimePast, only: set_timer, elapsed_time
implicit none
integer, parameter :: sgl=selected_real_kind(p=1) ! 单精度类型数
real(sgl) :: timeBTree, timeLLink, timeArray ! 声明各部分运行时间
type(binaryTreeName), pointer :: bTreeNode => null() ! 声明二叉树插入结点
type(binaryTreeName), pointer :: bTreeRoot => null() ! 声明二叉树根结点
type(linkedList), pointer :: lLinkNode => null() ! 声明链表插入结点
type(linkedList), pointer :: lLinkHead => null() ! 声明链表根节点
integer :: i ! 循环参数
integer :: errorLevel ! 错误状态码
real(sgl), dimension(50000) :: randomArray ! 随机数组
call set_timer ! 统计创造随机数组所需时间
do i = 1, 50000
call random_number(randomArray(i)) ! 给随机数组赋值
end do
call elapsed_time(timeArray)
call set_timer ! 统计二叉树排序所需时间
do i = 1, 50000
allocate(bTreeNode, stat=errorLevel) ! 创建插入结点
if ( errorLevel /= 0 ) stop "" ! 创建失败, 报错并退出
bTreeNode%var1 = randomArray(i) ! 给结点赋值
bTreeNode%before => null() ! 令插入结点前一结点为空
bTreeNode%next => null() ! 令插入结点后一结点为空
call BinaryTreeNameAdd(bTreeNode, bTreeRoot) ! 插入该结点
end do
call elapsed_time(timeBTree)
call set_timer ! 统计链表排序所需时间
do i = 1, 50000
allocate(lLinkNode, stat=errorLevel) ! 创建插入结点
if ( errorLevel /= 0 ) stop "" ! 创建失败, 报错并退出
lLinkNode%value = randomArray(i) ! 给结点赋值
lLinkNode%next => null() ! 令插入结点后一结点为空
call LinkedListAdd(lLinkNode, lLinkHead) ! 插入该结点
end do
call elapsed_time(timeLLink)
write(*, '(A, ES12.5, A)') &
&'创建数组共花费时间: ', timeArray, 's', &
&'排序二叉树共花费时间: ', timeBTree, 's', &
&'排序链表共花费时间: ', timeLLink, 's' ! 输出结果
! bTreeRoot => null()
! do i = 1, 50
! allocate(bTreeNode, stat=errorLevel)
! if ( errorLevel /= 0 ) stop ""
! bTreeNode%var1 = randomArray(i)
! bTreeNode%before => null()
! bTreeNode%next => null()
! call BinaryTreeNameAdd(bTreeNode, bTreeRoot)
! end do
! call BinaryTreeNamePrint(bTreeRoot)
end subroutine Exercises15_14
! 习题15-17 返回数组最大值指针
subroutine Exercises15_17
implicit none
interface ! 函数接口块
function MaxPtr(arrayInput) result(result)
implicit none
integer, parameter :: sgl=selected_real_kind(p=1)
real(sgl), intent(in), dimension(:), target :: arrayInput
integer :: i
integer :: maxLocate=1
real(sgl), pointer :: result
real(sgl) :: maxValue
end function MaxPtr
end interface
integer, parameter :: sgl=selected_real_kind(p=1) ! 单精度类型
integer :: i ! 循环参数
real(sgl), dimension(10), target :: randomArray ! 随机数组
real(sgl), pointer :: maxLocPtr => null() ! 最大值指针
do i = 1, 10
call random_number(randomArray(i)) ! 给随机数组赋值
end do
maxLocPtr => MaxPtr(randomArray) ! 计算最大值指针位置
write(*, *) 'The max value is ', maxLocPtr ! 输出结果
end subroutine Exercises15_17
function MaxPtr(arrayInput) result(result)
implicit none
integer, parameter :: sgl=selected_real_kind(p=1) ! 单精度类型
real(sgl), intent(in), dimension(:), target :: arrayInput ! 输入数组
integer :: i ! 循环参数
integer :: maxLocate=1 ! 最大值位置
real(sgl), pointer :: result ! 最大值指针(返回值)
do i = 2, ubound(arrayInput, 1) - lbound(arrayInput, 1) + 1
if ( arrayInput(maxLocate) < arrayInput(i) ) then
maxLocate = i ! 如果当前值比已有的最大值大, 那么最大值位置为当前位置
end if
end do
result => arrayInput(maxLocate) ! 将最大值指针指向输入数组最大值位置
end function MaxPtr
! 习题15-18 返回数组类型指针的最大值指针
subroutine Exercises15_18
implicit none
interface ! 函数接口块
function MaxPtr1(arrayInput) result(result)
implicit none
integer, parameter :: sgl=selected_real_kind(p=1)
real(sgl), intent(in), dimension(:), pointer :: arrayInput
integer :: i
integer :: maxLocate=1
real(sgl), pointer :: result
real(sgl) :: maxValue
end function MaxPtr1
end interface
integer, parameter :: sgl=selected_real_kind(p=1) ! 单精度类型
integer :: i ! 循环参数
real(sgl), dimension(:), pointer :: randomArray => null() ! 随机数组
real(sgl), pointer :: maxLocPtr => null() ! 最大值指针
integer :: errorLevel
allocate(randomArray(10), stat=errorLevel)
if ( errorLevel /= 0 ) stop
do i = 1, 10
call random_number(randomArray(i)) ! 给随机数组赋值
end do
maxLocPtr => MaxPtr1(randomArray) ! 计算最大值指针位置
write(*, *) 'The max value is ', maxLocPtr ! 输出结果
end subroutine Exercises15_18
function MaxPtr1(arrayInput) result(result)
implicit none
integer, parameter :: sgl=selected_real_kind(p=1) ! 单精度类型
real(sgl), intent(in), dimension(:), pointer :: arrayInput ! 输入数组
integer :: i ! 循环参数
integer :: maxLocate=1 ! 最大值位置
real(sgl), pointer :: result ! 最大值指针(返回值)
do i = 2, ubound(arrayInput, 1) - lbound(arrayInput, 1) + 1
if ( arrayInput(maxLocate) < arrayInput(i) ) then
maxLocate = i ! 如果当前值比已有的最大值大, 那么最大值位置为当前位置
end if
end do
result => arrayInput(maxLocate) ! 将最大值指针指向输入数组最大值位置
end function MaxPtr1
! 习题15-19 线性最小二乘拟合
! 程序过程:
! 1.打开一个临时文件, 并向其中写入数据
! 2.读取数据, 并将其添入链表
! 3.传递链表头指针给子程序, 子程序返回相应数值
module ModPoint
implicit none
integer, parameter :: sgl=selected_real_kind(p=1)
type :: point
real(sgl) :: x
real(sgl) :: y
type(point), pointer :: next
end type
end module ModPoint
subroutine Exercises15_19
use ModPoint
implicit none
interface ! 定义接口块
subroutine LeastSquaresMethodPtr(head, slope, intercept, correlationCoefficient)
use ModPoint
implicit none
type(point), intent(in), pointer :: head
real(sgl), intent(out) :: slope
real(sgl), intent(out) :: intercept
real(sgl), intent(out) :: correlationCoefficient
end subroutine LeastSquaresMethodPtr
end interface
type(point), pointer :: temp => null() ! 储存插入结点的临时值
type(point), pointer :: ptr => null() ! 操作结点
type(point), pointer :: head => null() ! 首结点
integer :: errorLevel ! 错误状态码
real :: m, b, r ! 最小二乘拟合参数
open(unit=1, status='scratch', iostat=errorLevel) ! 打开一个临时文件
if ( errorLevel /= 0 ) stop "" ! 打开失败, 报错退出
write(1, '(A)') & ! 输入文件值
&" -4.91, -8.18", &
&" -3.84, -7.49", &
&" -2.41, -7.11", &
&" -2.62, -6.15", &
&" -3.78, -5.62", &
&" -0.52, -3.30", &
&" -1.83, -2.05", &
&" -2.01, -2.83", &
&" -0.28, -1.16", &
&" +1.08, +0.52"
rewind(unit=1, iostat=errorLevel) ! 回到文件开头
if ( errorLevel /= 0 ) stop "" ! 操作失败, 报错退出
do
allocate(temp, stat=errorLevel) ! 给了临时结点分配内存
if ( errorLevel /= 0 ) stop "" ! 分配失败, 报错退出
temp%next => null() ! 临时节点的下一节点为空
read(1, *, iostat=errorLevel) temp%x, temp%y ! 给临时结点赋值
if ( errorLevel /= 0 ) then ! 如果没有输入值
deallocate(temp, stat=errorLevel) ! 释放临时结点的内存
if ( errorLevel /= 0 ) stop "" ! 释放内存失败, 报错退出
exit ! 释放内粗成功, 结束循环
end if
if ( .not. associated(head) ) then
head => temp ! 如果没有首结点, 则首结点指向临时节点
end if
if ( .not. associated(ptr) ) then
ptr => temp ! 如果操作结点不存在, 则操作结点指向临时节点
else
ptr%next => temp ! 如果操作结点存在, 则操作结点的下一个结点指向临时节点
ptr => ptr%next ! 操作结点指向临时节点
end if
end do
call LeastSquaresMethodPtr(head, m, b, r) ! 计算拟合结果
! arrayX = (/-4.91, -3.84, -2.41, -2.62, -3.78, -0.52, -1.83, -2.01, +0.28, +1.08&
! &, -0.94, +0.59, +0.69, +3.04, +1.01, +3.60, +4.53, +5.12, +4.43, +4.12/)
! arrayY = (/-8.18, -7.49, -7.11, -6.15, -5.62, -3.30, -2.05, -2.83, -1.16, +0.52&
! &, +0.21, +1.73, +3.96, +4.26, +5.75, +6.67, +7.70, +7.31, +9.05, 10.95/)
write(*,1) m, b, r ! 输出结果
1 format(1X, '计算得到的拟合方程为: y = ', F5.2, ' * x + ', F5.2, ' , 相关系数r为: ', F5.3)
end subroutine Exercises15_19
subroutine LeastSquaresMethodPtr(head, slope, intercept, correlationCoefficient)
use ModPoint
implicit none
type(point), intent(in), pointer :: head ! 首结点
real(sgl), intent(out) :: slope ! 斜率
real(sgl), intent(out) :: intercept ! 截距
real(sgl), intent(out) :: correlationCoefficient ! 相关系数
type(point), pointer :: ptr ! 操作结点
integer :: num=0 ! 结点总数
real :: x_bar, y_bar ! xy均值
real :: x_sum=0, y_sum=0 ! xy总和
real :: x2_sum=0, xy_sum=0, y2_sum=0 ! 各种参数
ptr => head ! 操作结点指向首结点
do
if ( associated(ptr) ) then ! 如果操作结点已关联
num = num + 1 ! 结点总数递增
x_sum = x_sum + ptr%x ! 计算各类参数
y_sum = y_sum + ptr%y
x2_sum = x2_sum + ptr%x**2
y2_sum = y2_sum + ptr%y**2
xy_sum = xy_sum + ptr%x*ptr%y
ptr => ptr%next ! 操作结点指向当前操作结点的下一个结点
else
exit ! 如果操作结点未关联, 则结束循环
end if
end do
x_bar = x_sum/real(num) ! x均值
y_bar = y_sum/real(num) ! y均值
slope = ( xy_sum - x_sum*y_bar )/( x2_sum - x_sum*x_bar ) ! 斜率
intercept = y_bar - slope*x_bar ! 截距
correlationCoefficient = ( real(num)*xy_sum - x_sum*y_sum )/& ! 相关系数
&sqrt( (real(num)*x2_sum - x_sum**2 )*( real(num)*y2_sum - y_sum**2 ) )
end subroutine LeastSquaresMethodPtr
! 习题15-20 双向链表
module ModDoLinkList
implicit none
integer, parameter :: sgl=selected_real_kind(p=1)
type :: doNode
real(sgl) :: var1
type(doNode), pointer :: before
type(doNode), pointer :: next
end type
contains
recursive subroutine DoNodeAdd(newNode, ptr)
type(doNode), intent(inout), pointer :: newNode
type(doNode), intent(inout), pointer :: ptr
if ( .not. associated(newNode) ) stop ""
if ( associated(ptr) ) then
if ( associated(ptr%next) ) then
call DoNodeAdd(newNode, ptr%next)
else
ptr%next => newNode
newNode%before => ptr
end if
else
ptr => newNode
end if
end subroutine DoNodeAdd
recursive subroutine DoNodeSort(ptr) ! 排序链表
implicit none
type(doNode), intent(inout), pointer :: ptr ! 操作指针
type(doNode), pointer :: newNode ! 需要变更的指针
type(doNode), pointer :: temp
integer :: errorLevel
write(*, '(A)', advance='no') ' 3'
if ( associated(ptr) .and. associated(ptr%next) ) then ! 如果操作指针及操作指针的下一个指针已关联
if ( ptr%var1 > ptr%next%var1 ) then ! 如果操作结点值大于下一个结点值
! allocate(newNode, stat=errorLevel)
! if ( errorLevel /= 0 ) stop ""
newNode => ptr%next ! 将变更指针 => 下一个结点
if ( associated(ptr%next%next) ) then ! 如果下一个结点不是最后一个结点
newNode%next%before => ptr ! 将变更结点的下一个结点的前指针 => 操作结点
ptr%next => newNode%next ! 操作结点的后指针 => 变更结点的下一个结点
else ! 如果下一个结点是最后一个结点
ptr%next => null() ! 操作结点的后指针 => 空
end if
newNode%before => null() ! 变更结点的前指针 => 空
newNode%next => null() ! 变更结点的后指针 => 空
write(*, '(A)', advance='no') '4'
! temp => ptr
call DoNodeSortForword(newNode, ptr%before) ! 将变更结点排序插入操作结点之前的链表
! ptr => temp
write(*, '(A)', advance='no') '5'
end if
write(*, '(A)', advance='no') '6'
if ( associated(ptr%next) ) then
call DoNodeSort(ptr%next) ! 对操作结点的下一个结点递归调用
end if
write(*, '(A)', advance='no') '7'
end if
end subroutine DoNodeSort
recursive subroutine DoNodeSortBackword(newNode, ptr)
implicit none
type(doNode), intent(in), pointer :: newNode
type(doNode), intent(inout), pointer :: ptr
if ( .not. associated(newNode) ) then
stop ""
else
if ( .not. associated(ptr) ) then
ptr => newNode
else
if ( newNode%var1 > ptr%var1 ) then
call DoNodeSortBackword(newNode, ptr%next)
else
newNode%before => ptr%before
ptr%before%next => newNode
newNode%next => ptr
ptr%before => newNode
end if
end if
end if
end subroutine DoNodeSortBackword
subroutine test1(value, ptr)
type(doNode), intent(inout), target :: value
type(doNode), intent(inout), pointer :: ptr
type(doNode), pointer :: temp => null()
type(doNode), target :: a
type(doNode), pointer :: newNode => null()
allocate(newNode)
newNode%var1 = 200.
newNode%before => null()
newNode%next => null()
a%var1 = 100.
a%before => null()
a%next => null()
temp => value%before
temp%next => a
write(*, *)
write(*, *) '如果传递的是值, 则 ', value%var1
temp => ptr%before
ptr%before%next => a
write(*, *) '如果传递的是指针, 则 ', ptr%var1
newNode%before => ptr ! 插入结点前指针 => 操作结点
temp => ptr%next
temp%before => newNode ! 操作结点后指针指向的结点的前指针 => 插入结点
newNode%next => temp ! 插入结点的后指针 => 操作结点后指针指向的结点
ptr%next => newNode
end subroutine
recursive subroutine DoNodeSortForword(newNode, ptr) ! 向前排序
implicit none
type(doNode), intent(inout), target :: newNode ! 插入结点
type(doNode), intent(inout), target :: ptr ! 操作结点
type(doNode), pointer :: temp
if ( newNode%var1 < ptr%var1 ) then ! 如果插入结点值比操作结点值小
if ( associated(ptr%before) ) then ! 如果操作结点前指针已关联
call DoNodeSortForword(newNode, ptr%before) ! 递归调用
else ! 如果操作结点前指针为空
ptr%before => newNode ! 操作结点前指针 => 插入结点
newNode%next => ptr ! 插入结点后指针 => 操作节点
end if
else ! 如果插入结点值比操作结点值大
newNode%before => ptr ! 插入结点前指针 => 操作结点
newNode%next => ptr%next
ptr%next => newNode
newNode%next%before => newNode
end if
end subroutine DoNodeSortForword
recursive subroutine DoNodeSortForword1(newNode, ptr) ! 向前排序
implicit none
type(doNode), intent(inout), pointer :: newNode ! 插入结点
type(doNode), intent(inout), pointer :: ptr ! 操作结点
type(doNode), pointer :: temp
write(*, *) '当前操作结点为: ', ptr%var1, '; 当前插入结点为:', newNode%var1
if ( .not. associated(newNode) ) then ! 如果插入结点未关联
stop "" ! 报错退出
else ! 如果插入结点已关联
write(*, *) ' 插入结点存在'
if ( newNode%var1 < ptr%var1 ) then ! 如果插入结点值比操作结点值小
write(*, *) ' 插入结点值小于操作结点值'
if ( associated(ptr%before) ) then ! 如果操作结点前指针已关联
write(*, *) ' 由于操作结点值前指针已关联, 检测前一结点'
call DoNodeSortForword1(newNode, ptr%before) ! 递归调用
else ! 如果操作结点前指针为空
write(*, *) ' 由于操作结点值前指针未关联, 则在最前端插入插入节点'
ptr%before => newNode ! 操作结点前指针 => 插入结点
newNode%next => ptr ! 插入结点后指针 => 操作节点
end if
else ! 如果插入结点值比操作结点值大
write(*, *) ' 插入结点值大于操作结点值, 将结点插入操作结点之后'
newNode%before => ptr ! 插入结点前指针 => 操作结点
write(*, *) ' 插入结点前指针指向: ', newNode%before%var1
temp => ptr%next
! ptr%next => newNode ! 操作结点的后指针 => 插入结点
temp%before => newNode ! 操作结点后指针指向的结点的前指针 => 插入结点
write(*, *) ' 操作结点后结点前指针指向:', temp%before%var1
newNode%next => temp ! 插入结点的后指针 => 操作结点后指针指向的结点
write(*, *) ' 插入结点后指针指向: ', newNode%next%var1
ptr%next => newNode
write(*, *) ' 操作结点后指针指向: ', ptr%next%var1
end if
! if ( .not. associated(ptr) ) then ! 如果操作结点前指针为空
! write(*, '(A)', advance='no') '10'
! ptr%before => newNode !
! newNode%next => ptr
! else
! write(*, '(A)', advance='no') '11'
! if ( newNode%var1 < ptr%var1 ) then
! call DoNodeSortForword(newNode, ptr%before)
! else
! newNode%before => ptr
! ptr%next%before => newNode
! newNode%next => ptr%next
! ptr%next => newNode
! end if
! end if
! newNode => null()
! call DoNodePrint1(ptr)
! write(*, *)
! ptr => null()
end if
end subroutine DoNodeSortForword1
recursive subroutine DoNodePrint(ptr)
type(doNode), intent(in), pointer :: ptr
if ( associated(ptr) ) then
write(*, '(F6.2)', advance='no') ptr%var1
call DoNodePrint(ptr%next)
end if
end subroutine DoNodePrint
recursive subroutine DoNodePrint1(ptr)
type(doNode), intent(in), pointer :: ptr
if ( associated(ptr) ) then
write(*, '(F6.2)', advance='no') ptr%var1
call DoNodePrint1(ptr%before)
end if
end subroutine DoNodePrint1
end module ModDoLinkList
subroutine Test
use ModDoLinkList
implicit none
type(doNode), pointer :: newNode => null()
type(doNode), pointer :: head => null()
type(doNode), pointer :: tail => null()
type(doNode), pointer :: ptr => null()
real(sgl) :: temp
integer :: i
integer :: errorLevel
do i = 1, 21
allocate(newNode)
newNode%var1 = real(i)
newNode%before => null()
newNode%next => null()
if ( .not. associated(head) ) head => newNode
! if ( .not. associated(head) ) then
! head => newNode
! write(*, *) '已插入首结点 ', newNode%var1
! else
! call DoNodeAdd(newNode, head)
! write(*, *) '已插入结点 ', newNode%var1
! end if
call DoNodeAdd(newNode, tail)
tail => newNode
end do
allocate(newNode)
newNode%var1 = 17.5
newNode%before => null()
newNode%next => null()
ptr => head
do
if ( associated(ptr) ) then
write(*, '(F6.2)', advance='no') ptr%var1
ptr => ptr%next
else
exit
end if
end do
write(*, *)
ptr => tail
call DoNodeSortForword1(newNode, ptr)
call DoNodePrint(head)
write(*, *)
call DoNodePrint1(tail)
write(*, *)
do
if ( associated(head%before) ) then
head => head%before
else
exit
end if
end do
ptr => tail
ptr => head
write(*, *)
do
if ( associated(ptr) ) then
write(*, '(F6.2)', advance='no') ptr%var1
! write(*, *) '当前结点值为:', ptr%var1, '; 下一结点值为:', ptr%before%var1
! ptr => ptr%before
ptr => ptr%next
else
exit
end if
end do
ptr => tail%before
call test1(ptr, ptr)
write(*, *) ptr%before%var1, ptr%var1, ptr%next%var1, ptr%next%next%var1
end subroutine Test
subroutine Exercises15_20
use ModDoLinkList
implicit none
integer :: i
type(doNode), pointer :: newNode => null()
type(doNode), pointer :: head => null()
type(doNode), pointer :: tail => null()
type(doNode), pointer :: ptr => null()
real(sgl) :: temp
integer :: errorLevel
open(unit=1, status='scratch', iostat=errorLevel)
if ( errorLevel /= 0 ) stop ""
do i = 1, 20
call random_number(temp)
temp = temp*200_sgl - 100_sgl
write(1, *, iostat=errorLevel) temp
if ( errorLevel /= 0 ) stop ""
end do
rewind(unit=1, iostat=errorLevel)
if ( errorLevel /= 0 ) stop ""
do
read(1, *, iostat=errorLevel) temp
if ( errorLevel /= 0 ) exit
allocate(newNode, stat=errorLevel)
if ( errorLevel /= 0 ) stop ""
newNode%var1 = temp
newNode%before => null()
newNode%next => null()
if ( .not. associated(head) ) then
head => newNode
end if
if ( .not. associated(ptr) ) then
ptr => newNode
else
ptr%next => newNode
newNode%before => ptr
ptr => newNode
end if
tail => ptr
end do
ptr => head
write(*, *) "从前向后排列:"
do
if ( associated(ptr) ) then
write(*, '(F10.5)', advance='no') ptr%var1
ptr => ptr%next
else
write(*, *) ''
exit
end if
end do
ptr => tail
write(*, *) "从后向前排列:"
do
if ( associated(ptr) ) then
write(*, '(F10.5)', advance='no') ptr%var1
ptr => ptr%before
else
write(*, *) ''
exit
end if
end do
end subroutine Exercises15_20
subroutine Exercises15_21
use ModDoLinkList
implicit none
integer :: i
type(doNode), pointer :: newNode => null()
type(doNode), pointer :: head => null()
type(doNode), pointer :: tail => null()
type(doNode), pointer :: ptr => null()
real(sgl) :: temp
integer :: errorLevel
open(unit=1, status='scratch', iostat=errorLevel)
if ( errorLevel /= 0 ) stop ""
do i = 1, 50
call random_number(temp)
temp = temp*2000_sgl - 1000_sgl
write(1, *, iostat=errorLevel) temp
if ( errorLevel /= 0 ) stop ""
end do
rewind(unit=1, iostat=errorLevel)
if ( errorLevel /= 0 ) stop ""
do
read(1, *, iostat=errorLevel) temp
if ( errorLevel /= 0 ) exit
allocate(newNode, stat=errorLevel)
if ( errorLevel /= 0 ) stop ""
newNode%var1 = temp
newNode%before => null()
newNode%next => null()
if ( .not. associated(head) ) then
head => newNode
end if
if ( .not. associated(ptr) ) then
ptr => newNode
else
ptr%next => newNode
newNode%before => ptr
ptr => newNode
end if
tail => ptr
end do
ptr => head
write(*, *) "从前向后排列:"
do
if ( associated(ptr) ) then
write(*, '(F10.5)', advance='no') ptr%var1
ptr => ptr%next
else
write(*, *) ''
exit
end if
end do
ptr => head
write(*, *) 1
call DoNodeSort(ptr)
write(*, *) 2
ptr => head
do
if ( associated(ptr%before) ) then
ptr => ptr%before
else
head => ptr
exit
end if
end do
ptr => tail
do
if ( associated(ptr%next) ) then
ptr => ptr%next
else
tail => ptr
exit
end if
end do
ptr => head
write(*, *) "升序排列:"
do
if ( associated(ptr) ) then
write(*, '(F10.4)', advance='no') ptr%var1
ptr => ptr%next
else
write(*, *) ''
exit
end if
end do
ptr => tail
write(*, *) "降序排列:"
do
if ( associated(ptr) ) then
write(*, '(F10.4)', advance='no') ptr%var1
ptr => ptr%before
else
write(*, *) ''
exit
end if
end do
end subroutine Exercises15_21
module ModDuLinkList
implicit none
private
type :: duNode
end module ModDuLinkList
subroutine Exercises15_21new
use ModDuLinkList
implicit none
end subroutine Exercises15_21new