有趣生活

当前位置:首页>科技>数字数据分析模型数形结合与数据结构

数字数据分析模型数形结合与数据结构

发布时间:2026-07-25阅读(0)

导读如何用数学的方法表白?据说在1650年的斯德哥尔摩街头,笛卡尔52岁时邂逅了18岁的瑞典公主克里斯汀,他成了公主的数学老师。后来,笛卡尔被流放回法国,总共给....

如何用数学的方法表白?

据说在1650年的斯德哥尔摩街头,笛卡尔52岁时邂逅了18岁的瑞典公主克里斯汀,他成了公主的数学老师。

后来,笛卡尔被流放回法国,总共给公主寄出过13封情书,也就是在最后一封信中,只有短短的一个数学公式:r = a(1-sinθ)

而这位公主呢,她恰好是个低调的数学迷,她一眼就看破了其中真意,于是优雅地在纸上,在直角坐标系中将曲线画了出来,于是一个心形图案跃然纸上。

这里的θ表示角度值,心形曲线就是当a=1时,(1-sinθ)对应的曲线。

#include <stdio.h>#include <math.h>#define pi 3.1415926int main(){ for(int i=0;i<=360;i =15) { printf("= %.2f\n",i,1*(1-sin(pi*i/180.0))); } getchar();}/* 0 1.00 15 0.74 30 0.50 45 0.29 60 0.13 75 0.03 90 0.00105 0.03120 0.13135 0.29150 0.50165 0.74180 1.00195 1.26210 1.50225 1.71240 1.87255 1.97270 2.00285 1.97300 1.87315 1.71330 1.50345 1.26360 1.00*/

当a取不同值时:

坐标系平移一个单位的水平方向:

1 数形结合思想

自从欧几里德的《几何原本》问世以来,人们一直把代数限定在研究数及其关系的范畴内,把几何限定在研究位置和图形的范畴内。

代数和几何截然分家持续了几千年,犹如两座高山被万丈深渊分割,连接代数和几何的桥梁将“数”和“形”紧密联系在一起的科学就是笛卡儿创立的坐标几何学,数形结合思想就此产生。图形难言状,坐标来帮忙。

数学思想方法可以说是数学的灵魂和精髓,而数形结合思想是数学解题当中最常用、最重要的数学思想方法之一。

数与形是数学中两个最古老、最基本的元素,是数学大厦深处的两块基石,所有的数学问题都是围绕数和形的提炼、演变、发展而展开的:每一个几何图形中都蕴藏着一定的数量关系,而数量关系又常常可以通过图形的直观性作出形象的描述

数形结合将抽象数学语言和直观图像结合起来:

代数问题几何化--------以形助数

几何问题代数化--------以数定形

因此,在解决数学问题时,常常根据数学问题的条件和结论之间的内在联系,将数的问题利用形来观察,提示其几何意义;而形的问题也常借助数去思考,分析其代数含义

如此将数量关系和空间形式巧妙地结合起来,并充分利用这种“结合”,寻找解题思路,使问题得到解决的方法。

简言之,就是把数学问题中的数量关系和空间形式相结合起来加以考察的处理数学问题的方法,称之为数形结合的思想方法。

我国著名数学家华罗庚曾说:“数缺形时少直观,形少数时难入微;数形结合百般好,隔离分家万事休”。

数形结合就是把抽象的数学语言、数量关系与直观的几何图形、位置关系结合起来, 通过"以形助数"或"以数解形"即通过抽象思维与形象思维的结合,可以使复杂问题简单化,抽象问题具体化,从而起到优化解题途径的目的。

在运用数形结合思想分析和解决问题时,要注意三点:

① 要彻底明白一些基础概念和运算的几何意义以及函数图象的代数特征;

② 恰当设未知数建立关系,由数思形,以形想数,做好数形转化;

③ 正确确定未知数的取值范围。

数形结合作为一种数学思想方法,其应用大致又可分为两种情形:

一是借助于数的精确性来阐明形的某些属性;

二是借助形的几何直观来阐明数间某种关系。

换句话说,数形结合包括三个方面:以数化形、以形变数、形数互变。

以数化形

由于“数”和“形”是一种对应,有些数量比较抽象,我们难以把握,因此我们可以把“数”的对应“形”找出来,利用图形来解决问题。

以形变数

虽然形有形象直观的优点,但在定量方面还必须借助代数的计算,充分利用图形的性质或几何意义,把“形”正确表示成“数”的形式,进行分析计算。

形数互变

在有些数学问题中不仅仅是简单的“以数变形”或“以形变数”而是需要形数互相变换,不但要想到由形的直观变为“数”的严密还要由“数”的严密联系到"形"的直观。

总之,数形结合是将抽象的数学语言与直观图形结合起来,不仅能直观地发现解题的途径,而且能避免复杂的计算与推理,大大简化解题的过程。

2 不需要语言的直观证明

数形的巧妙结合,一些数学问题便可以直观地用图形表示出来。

1 3 5 … (2n-1)=?如图,毕达哥拉斯早已利用图形给出了几何解释。

如下图所示,由谢尔宾斯基三角形可以得出:

3 数形结合与内存分区、内存模型

编程时也需要数形结合的思想,对数的二进制编码、数据结构的内存分布、对象的内存模型、内存对齐了然于形。

3.1 C、C 、java程序的内存模型

3.2 指针

指针变量是对指针所指地址及其需取内存字节数量、编码方案及可以适用的目标类型的操作的描述。

指针的目标类型是指针声明去年指针声明符*和标识符后剩下的部分。

3.3 对象内存模型:

类实例化为对象后实际分配内存,各成员数据按内存对齐的方式紧挨在一起,对象名就是这一大块内存的首地址(基准地址),数据成员员就是对这一基准地址的位置偏移。同样的,在内存的代码区,也可以以对象名为基准访问到各成员函数的首地址。

# include <iostream>using namespace std;//类对象的成员变量、成员函数内存测试 class Base{public://成员函数 void foo1(){}void foo2(){}public://成员变量 double m_fMember1;int m_nMember2;long m_nMember3;short m_nMember4;};

对象的第一个成员变量的地址跟整个对象的地址相同,第二个成员变量紧跟其后。对象中的成员变量是按照类声明中的顺序依次排列的(可能会有内存对齐的情况)。

(结构体的内存映像类似于类的数据成员映像。)

而类的成员函数都被放在一个特殊的位置(因为同一类的所有对象的成员函数都是相同的,没有必要为每个对象配备一份),所有这个类的对象都共用这份成员函数。如下图:

带有虚函数的内存模型:

4 数形结合与数据结构

数据结构,特别是链式结构的增、删、查等操作,结合图形,容易理解代码思路。

4.1 线性结构

4.1.1 顺序存储结构

4.1.1.1 顺序表(Sequence List)

顺序表数据结构

typedef struct { ElemType *elem; int length; int size; int increment;} SqList;

数形结合:

遍历代码:

//遍历顺序表Lbool ListTraverse_Sq(SqList L, Status(*visit)(ElemType e)) { if(0 == L.length) return false; for(int i = 0; i < L.length; i ) { printf("%d\t", e); } return true; }

4.1.1.2 顺序栈(Sequence Stack)

顺序栈数据结构

typedef struct { ElemType *elem; int top; int size; int increment;} SqSrack;

数形结合:

核心代码摘录:

//元素e压入栈Sbool Push_Sq(SqSrack &S, ElemType e) { ElemType *newbase; if(S.top >= S.size) { newbase = (ElemType *)realloc(S.elem, (S.size S.increment) * sizeof(ElemType)); if(NULL == newbase) return false; S.elem = newbase; S.size = S.increment; } S.elem[S.top ] = e; return true;}//栈S的栈顶元素出栈,并用e返回bool Pop_Sq(SqSrack &S, ElemType &e) { if(0 == S.top) return false; e = S.elem[S.top - 1]; S.top--; return e;}

4.1.1.3 顺序队列(Sequence Queue)

队列数据结构

typedef struct { ElemType * elem; int front; int rear; int maxSize;}SqQueue;

① 非循环顺序队列

数形结合:

② 顺序循环队列

数形结合:

SqQueue.rear = (SqQueue.rear 1) % SqQueue.maxSize

4.1.2 链式线性结构

链式数据结构

typedef struct LNode { ElemType data; struct LNode *next;} LNode, *LinkList;

线性表的链式表示

单链表(Link List)

遍历单链表

bool visit(ElemType e) { printf("%d\t", e); return true;}//遍历单链表void ListTraverse_L(LinkList L, bool(*visit)(ElemType e)){ if(NULL == L) return; for(LinkList p = L; NULL != p; p = p->next) { visit(p->data); }}

插入结点:

删除结点:

#include <stdio.h>#include <malloc.h>typedef struct node { int num; struct node *next;} Node, *NodePtr;NodePtr createList() // 使用头节点{ NodePtr top = (NodePtr)malloc(sizeof(Node)); if(top==NULL) { printf("malloc failed!\n"); return top; } top->num = 0; // 也可以用来存储链表长度 top->next = NULL; return top;}NodePtr makeNode(int n) { NodePtr np = (NodePtr) malloc(sizeof (Node)); if(np==NULL) { printf("malloc failed!\n"); return np; } np -> num = n; np -> next = NULL; return np;}void insertListFromHead(NodePtr top,int n) { NodePtr np = makeNode(n); np->next = top->next; top->next = np;}NodePtr searchListPrev(NodePtr top,int num){ NodePtr prev = top->next; NodePtr curr = NULL; if(prev!=NULL) curr = prev->next; while(curr!=NULL && curr->num != num) { prev = curr; curr = prev->next; } return prev;}void deleteFromPrev(NodePtr top,int n) { NodePtr prev = searchListPrev(top,n); NodePtr curr = prev->next; if(prev!=NULL){ prev->next = curr->next; if(curr!=NULL) free(curr); }}void printList(NodePtr top) { NodePtr curr = top->next; while (curr != NULL) { // as long as theres a node printf("%d ", curr -> num); curr = curr -> next; // go on to the next node } printf("\n");} void destroyList(NodePtr* top){ NodePtr next = (*top)->next; while(next!=NULL) { free(*top); *top = next; next = next->next; } free(*top); *top = NULL;}int main(){ NodePtr top = createList(); int arr[] = {23,52,15,36}; int n = sizeof arr / sizeof *arr; for(int i=n-1;i>=0;i--) insertListFromHead(top,arr[i]); printList(top); deleteFromPrev(top,15); printList(top); destroyList(⊤); getchar(); return 0;}/*23 52 15 3623 52 36*/

双向链表(Du-Link-List)

循环链表(Cir-Link-List)

链队列(Link Queue)

4.2 二叉树数据结构

4.2.1 二叉树顺序存储

以下二叉树一般可以使用顺序存储:

满二叉树

完全二叉树(堆)大顶堆:根 >= 左 && 根 >= 右小顶堆:根 <= 左 && 根 <= 右

4.2.2 二叉树链式存储

typedef struct BiTNode{ TElemType data; struct BiTNode *lchild, *rchild;}BiTNode, *BiTree;

demo:

// 构建二叉树BiTree MakeBiTree(TElemType e, BiTree L, BiTree R){ BiTree t; t = (BiTree)malloc(sizeof(BiTNode)); if(NULL == t) return NULL; t->data = e; t->lchild = L; t->rchild = R; return t;}

线性结构实现二叉存储,可以达到二分法的查找效率

二叉查找树(二叉排序树):左 < 根 < 右

  • 平衡二叉树(AVL树):| 左子树树高 - 右子树树高 | <= 1
  • 最小失衡树:
  • 平衡二叉树插入新结点导致失衡的子树:调整:
  • LL型:根的左孩子右旋
  • RR型:根的右孩子左旋
  • LR型:根的左孩子左旋,再右旋
  • RL型:右孩子的左子树,先右旋,再左旋

树的孩子兄弟表示法与二叉树:

树的孩子兄弟表示法可以把一棵复杂的树变成了一棵二叉树。

用二叉链表作为树的存储结构,链表中每个结点的两个指针域分别指向其 第一个孩子结点 和 下一个兄弟结点。

typedef struct CSNode{ ElemType data; struct CSNode *firstchild, *nextsibling;}CSNode, *CSTree;

图形:

4.3 图的思维导图:

ref

https://www.bookstack.cn/books/cpp-interview

https://github.com/huihut/interview/tree/master/DataStructure

https://www.toutiao.com/article/6537063899198390797

Copyright © 2024 有趣生活 All Rights Reserve吉ICP备19000289号-5 TXT地图HTML地图XML地图