考研数据结构笔记 诸论
一、代码书写规范
1.数据类型
(1)结构型
结构型可以理解为用户已有数据类型(int,char,float)为原料制作的数据类型。
typedef struct
{
int a;
char b;
float c;
}TypeA;
(2)指针型
指针型变量里装的是变量的地址,指出了某个变量的位置。
int *a;//定义变量语句:int a;
char *b;//定义变量语句:char b;
float *c;//定义变量语句:float c;
TypeA *d;//定义变量语句:TypeA d;
如果a是个指针型变量,且它已经指向了一个变量b,则a中存放变量b所在的地址。*a就是取变量b的内容(x=*a;等价于x=b),&b就是取量b的地址,语句a=&b;就是将变量b 的地址存于a中,即指针a指向b。
(3)结点的构造
tppedef struct Node
{
int data;
struct Node *next;
}Node;
1)结点的构造
凡是结构型(假设名为a)内部有这样的指针型(假设名为b),即b是用来存放和a类型相同的结构体变量地址的指针型,则在定义a的typedef struct语句之后都要加上a这个结构型的名字、
2)二叉树结点的定义
<span style="color:文字颜色;background:背景颜色;font-size:文字大小;font-family:字体;">你要改色的文字</span> 修改字体颜色
这个多出* btnode等价于BTNode,可以删去,统一的BTNode就可以解决问题
typedef struct BTNode
{
int datda;
struct BTNode *lchirld;
struct BTNode *rchirld;
}BTNode;
typedef struct BTNode
{
int datda;
struct BTNode *lchirld;
struct BTNode *rchirld;
}BTNode,*btnode;
1.BTNode BT;
2.BTNode *BT;
BT=(BTNode*)malloc(sizeof(BTNode));//要熟练 结点空间申请函数
1中只用一句就制作了一个结点,而2中需要两句,比1要繁琐,但考研中用得最多的是2。2的执行过程:先定义有个结点的指针BT,然后用函数malloc()来申请有个结点的内存空间,最后让指针BT指向这片内存空间。
int *p;
p=(int *)malloc(n*sizeof(int));
申请了一个由指针p所指的(p指向数组中第一元素的地址)、元素为int型的、长度为n的动态数组。取元素的时候和一般的数组(静态数组)一样。
sizeof是运算符,不是函数,可以把它当做一个以数据类型为参数,返回值为传入数据类型所占存储空间大小的函数理解
3)关于typedef和#define
(1)typedef可以理解为给现有的数据类型起有个新的名字。
如果想想给int型起个新名字A,可写成typedef int A;定义整型变量时,A x就等价于int x.
(2)#define认识就好
2.函数
(1)被传入的函数的参数值是否会改变
int a;
void f(int x)
{
++X;
}
1.a=0;
2.f(a)//值还是0,没有被改变
因为对于函数f()在调用它的时候,括号里的变量a和1中的变量a不是同一变量。
如果要改变f()函数体内的值
void f(int &x)
{
++X;
}
如果传入的变量是指针变量
void f(int *&x)//指针型变量在函数体需要改变的写法
{
++x;
}
一维数组作为函数参数
void f(int x[],int n)
{
....''
}
二维数组作为函数参数
void (int x[] [maxSize],int n)
{
....;
}
void f(int x[][5])
{
....;
}
int a[10][5];
int b[10][3];
f(a);//参数正确
f(b);//参数错误
(2)关于参数引入型的其他例子
1)
void insert(Sqlist &L,int x)
{
//因为L本身要发生改变,所以要用引用型
int p,i;
p=LocateElemt(L,x);
for(i=L.length-1;i>-p;--i)
L.data[i+1]=L.data[i];
L.data[p]=x;
++(L.length);
}
讲解:L是个结构体类型(Sqlist型),data[]数组是他的一个分量,属于Sqlist的一部分,data改变就是自身改变,使用函数insert()目的是在data[]数组中插入一个元素,使data[]数组内容改变,L也随之改变,因此传入L要用引用型。
2)
int SearchAndDelete(LNode *C,int x)
{
LNode *p,*q;
p=C;
while(P->next!=Null)
{
if(p->next!=NULL)
break;
p=p->next;
}
if(p->next==NULL)
return 0;
else{
q=p->next;
p->next=p->next->next;
free(q);
return 1;
}
}
讲解:C是一指向一个链表表头的指针,主义仅仅是个指针,和1)中的L不一样,他不代表整个链表,函数SearchAndDelete()删除被操作的链表中除C所指结点(头结点不含链表元素信息)以外的所有结点,导致链表相关指针改变,但C指针自己不便,因此这里传入C的时候不需要用引用型。
3)
void merge(LNode *A,LNode *B,LNode *&C)
{
LNode *p=A->next;
LNode *q=B->next;
LNode *r;
C=A;
C->next=NULL;
free(B);
r=C;
}
讲解:将A、B两个链表合并成一个,此时需要得到一个指向结果链表的指针,就是参数C。C指针在传入时可能是一个空指针,经过函数操作后它指向接连不熬表头结点,显然C自身发生了改变需要引用型,A,B没有改变的必要,因此不需要引用型。
(3)有返回值的函数
定义一个函数:
int f(int a)
{
return a;
}
二、算法的时间复杂度与空间复杂度分析
1.时间复杂度
将算法中基本操作的执行次数作为算法时间复杂度的度量。
常用复杂度比较关系
O(1)<=O(log2(n))<=O(n)<=O(nlog2(n))<O(n2)<=O(n3)<=…<=O(nk)<=O(2n)
具体步骤:1.确定算法中基本操作以及问题的规模。
2.根据基本操作执行情况计算出规模n的函数f(n),并确定时间复杂度为T(n)=O(f(n))中增长最快的项/此项的系数
一般依照使得基本操作执行次数最多的输入来计算时间复杂度,即将最坏的情况作为算法时间复杂度的度量
例题p12
做题方法:
1.找基本操作
2.确定规模
2.空间复杂度
算法的空间复杂度指算法在运行时所需存储空间的度量,主要考虑在算法运行过程中临时占用的存储空间的大小。
三、数据结构的基本概念
1.数据
数据是对客观事物的符号的表示。
2.数据元素
数据元素是数据的基本单位
3.数据对象
数据对象是性质相同的数据元素的集合,是数据的一个子集
4.数据结构
数据结构是相互之间存在一种或多种特定关系的数据元素的集合。,包括,逻辑结构,存储结构和对数据的运算。
5.数据的逻辑结构
数据的逻辑结构是对数据之间的关系描述
(1)线性结构
(2)非线性结构
6.数据的物理结构
(1)顺讯存储结构
(2)链式存储结构
(3)索引存储方法
一般形式为<关键字,地址>关键字标识唯一一个结点,地址作为指向结点的指针。
(4)散列存储结构
结点的关键字通过散列函数直接计算出该结点的存储地址。本质是顺序存储方法的扩展。
7.算法的特性
(1)有穷性
(2)确定性
(3)输入
(4)输出
(5)可行性
8.算法的设计目标
(1)正确性
(2)可读性
(3)健壮性
(4)高效率与低存储量需求