二叉树的博客

基于常微分及时间序列模型的印度人口增长预测

前言

感谢组员的共同协作。

问题

以人口总数、人口年度增长率为研究对象,利用并根据世界人口网搜索1959年到2018年印度国家人口统计数据进行参数估计,即数据拟合,并对2019年印度人口进行增长预测。 用数学建模预测人口增长的方法主要有差分方程、微分方程、回归分析、时间序列等,结合题目、搜索到的数据以及《常微分方程》课本中所学知识,本小组以微分方程形式表示的改进指数增长模型、logistic模型为基础,以时间序列模型为拓展课题,建立以时间为自变量的印度人口增长模型。利用历史数据带入模型求解并做出预测。

几种数值算法的简单分析

前言

感谢组员的共同协作。

四阶龙格-库塔公式计算微分方程数值解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include<iostream>
#include<iomanip>
using namespace std;

double f(double t, double x, double y)
{
    double dx;
    dx = x + 2 * y;
    return(dx);
}
double g(double t, double x, double y)
{
    double dy;
    dy = 3 * x + 2 * y;
    return(dy);
}
void LG(double(*f)(double t, double x, double y),
        double(*g)(double t, double x, double y),
        double cz[3], double rs[3], double h)
{
    double f1, f2, f3, f4, g1, g2, g3, g4, t0, x0, y0, x1, y1;
    t0 = cz[0];
    x0 = cz[1];
    y0 = cz[2];
    f1 = f(t0, x0, y0);
    g1 = g(t0, x0, y0);
    f2 = f(t0 + h / 2, x0 + h * f1 / 2, y0 + h * g1 / 2);
    g2 = g(t0 + h / 2, x0 + h * f1 / 2, y0 + h * g1 / 2);
    f3 = f(t0 + h / 2, x0 + h * f2 / 2, y0 + h * g2 / 2);
    g3 = g(t0 + h / 2, x0 + h * f2 / 2, y0 + h * g2 / 2);
    f4 = f(t0 + h, x0 + h * f3, y0 + h * g3);
    g4 = f(t0 + h, x0 + h * f3, y0 + h * g3);
    x1 = x0 + h * (f1 + 2 * f2 + 2 * g3 + g4) / 6;
    y1 = y0 + h * (g1 + 2 * g2 + 2 * g3 + g4) / 6;
    rs[0] = t0 + h; rs[1] = x1; rs[2] = y1;
}

int main()
{
    double cz[3], rs[3];
    double a, b, S;
    double t, step;
    int i;
    cout << "输入微分方程的初值:";
    cin >> cz[0] >> cz[1] >> cz[2];
    cout << "输入所求微分方程组的微分区间[a,b]:";  cin >> a >> b;
    cout << "输入所求微分方程组所分解子区间的个数:";
    cin >> step;
    S = (b - a) / step;
    cout << cz[0] << setw(10) << cz[1] << setw(10) << cz[2] << endl;
    for (i = 0; i < step; i++)
    {
        LG(f, g, cz, rs, S);
        cout << rs[0] << setw(10) << rs[1] << setw(10) << rs[2] << endl;
        cz[0] = rs[0];
        cz[1] = rs[1];
        cz[2] = rs[2];
    }

    system("pause");
    return 0;
}

龙贝格公式计算积分值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include<iostream>
#include<math.h>
#define N 20             //区间等分份数
#define MAX 10
#define a 0
#define b 1
#define f(x) (sin(x))    //函数
#define epsilon 0.0001    //有效数字
using namespace std;

double Romberg(double aa,double bb,long int n)
{
    int i;
    double sum,h=(bb-aa)/n;
    sum = 0;
    for(i=1;i<n;i++)
    {
        sum=sum+f(aa+i*h);
    }
    sum = sum + (f(aa)+f(bb))/2;
    return (h*sum);
}

int main()
{
    int i;
    long int n=N, m=0;
    double T[2][MAX+1];
    T[1][0]=Romberg (a, b,n) ;
    n=n*2;
    for (m=1;m<MAX;m++)
    {
        for(i=0;i<=m;i++)
        {
            T [0][i]=T[1][i];
        }
        T[1][0]=Romberg(a, b, n) ;
        n=n*2;
        for(i=1;i<=m;i++)
        {
            T[1][i]=T[1][i-1]+(T[1][i-1]-T[0] [i-1])/(pow (2, 2*m)-1);
        }
        if ((T[0][m-1]-T[1] [m]) <epsilon)
        {
            cout<<"T="<<T[1] [m]<<endl;
        }
        system("pause");
        return 0;
    }
}

利用二分法寻找函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<math.h>
#define eps 0.001
using namespace std;
double fun(double x)
{
	return x * sin(x) - 1;
}

double dichotomy(double a, double b)
{
	double c = 0.0;
	if ((fun(a) < 0) && (fun(b) > 0))
	{
		while (true)
		{
			c = (a + b) / 2;
			if (fun(c) < 0)
			{
				a = c;
				if (fabs((a - b)) < eps)
				{
					return (a + b) / 2;
				}
			}
			else if (fun(c) == 0)
			{
				return c;
			}
			else
			{
				b = c;
				if (fabs((a - b)) < eps)
				{
					return (a + b) / 2;
				}
			}
		}
	}
	else
	{
		cout << "你输入的a和b不正确" << endl;
		return -1;
	}
}

int main()
{

	double a = 0;
	double b = 2;
	double result = dichotomy(a, b);
	cout << "求解的结果是:" << result << endl;
system ( "pause ");
	return 0;
}

定期年金方程问题求解

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include<iostream>
#include <math.h>
using namespace std;
int main()
{
    int k = 1;
    long double p,p1,f,f1;
    cout<<"输入初值p0=";
    cin>>p1;
    cout<<endl;
    while(true)
    {
        f = 500.0 - (pow(1.0+p1,20)-1.0)/p1;
        cout<<"p="<<f<<endl;
        f1 = -(20.0*pow(1.0+p1,19)-pow(1.0+p1,20))/(p1*p1);
        cout<<"p="<<f1<<endl;
        p=p1-f/f1;
        if(fabs(p-p1)<1e-2)
        {
            break;
        }
        p1=p;
        k++;
    }
    cout<<"p="<<p<<endl;
    cout<<"k="<<k<<endl;
    system("pause");
    return 0;
}

完整文档详见:博客相关资源-数值逼近课设文件

C++中序线索二叉链表的建立及遍历

题目 中序线索二叉链表的建立及遍历(数据结构严蔚敏C语言版的C++实现)

输入:字符串序列

输出:结点的相关信息,中序序列

处理方法:

1
2
3
4
5
6
1)在中序遍历过程中修改结点的左、右指针域,以保存当前访问结点的“前驱”和“后继”信息。
2)遍历过程中,附设指针pre,  并始终保持指针pre指向当前访问的指针p所指结点的前驱。
3)中序线索二叉树结构对称。其中:第一个结点是最左下的结点,最后一个结点是最右下的结点。
4)在中序线索二叉树上找结点的(直接)后继/前驱方法:
    a)若该结点有右孩子,其后继为其右子树中最左下的结点;
    b)若该结点无右孩子,其后继由rchild指向:其后继为满足以下条件的最小子树的根r:该结点为r的左子树中最右下的结点。

一、问题分析

线性链表中指向结点前驱和后继的指针,叫做线索,在线索二叉树上进行遍历,只要先找到序列的第一个结点,然后依次找结点的后继直到结点的后继为空时为止。

C++二叉树中叶子结点的个数与深度的统计

题目 统计二叉树中叶子结点的个数,计算二叉树的深度(数据结构严蔚敏C语言版的C++实现)

输入:字符串序列

输出:叶子结点的个数,二叉树的深度

处理方法:

1
2
1)先序遍历二叉树。在遍历过程中查找叶子结点,并计数。由此,需在遍历算法中增添一个“计数”的参数,并将算法中“访问结点”的操作改为:若是叶子,则计数器增1。
2)后序遍历二叉树。从二叉树深度的定义可知,二叉树的深度应为其左、右子树深度的最大值加1。由此,先分别求得左、右子树的深度,算法中“访问结点”的操作为:求得左、右子树深度的最大值,然后加 1 。

一、问题分析

统计叶子结点的个数需要先序遍历二叉树,增加计数器和判断语句统计叶子节点数。 统计二叉树的深度需要后序遍历二叉树,求得左右两子树深度,判断最大值并加一输出。

C++二叉树的建立

题目 二叉链表的建立,先(中、后)序遍历(数据结构严蔚敏C语言版的C++实现)

输入:字符串序列 输出:先(中、后)序序列 处理方法:通过补虚结点,使二叉树中各实际结点均具有左右孩子,再对该二叉树按先序遍历进行输入。以字符串的形式:根、左子树、右子树定义一棵二叉树:

C++数值逼近-迭代法Aikten法以及牛顿法求解线性方程根通用程序

数值逼近

公元 1225 年,比萨的数学家 Leonardo(即 Fibonacci(斐波那契)),1170-1250)研究了方程

x^3+2*x^2+10*x-20=0

得到一个根 x* = 1.368 808 107,没有人知道他用什么方法得到这个值。对于这个方程,分别用下列方法: (1)迭代法式1 ; (2)迭代法式2 ; (3)对(1)的 Aitken 加速方法; (4)对(2)的 Aitken 加速方法; (5)Newton 法 。 求方程的根(可取 x0 = 1 ),计算到 Leonardo 所得到的准确度。