数据结构 = 个体的存储(数据) + 个体关系的存储(数据结构)
解决一个问题(模拟一个问题) = 一个个不可再分的个体 + 个体与个体之间的关系 + 解决问题的算法
算法 = 对数据的操作方式(解题的方法和步骤)
各种语言中的堆栈等概念。
操作系统中的某些概念。
数据库中的字段 记录 表等概念。
程序 = 数据的存储 + 数据的操作 + 可以被计算机执行的语言
1.时间复杂度
大概程序要执行的次数(硬件不断升级,衡量时间没有意义,次数越少,效率越高)
2.空间复杂度
算法执行的过程中大概所占用的最大内存
3.难易程度(可读性)
别人是否可以理解你的算法
4.健壮性
对于非法数据的承受能力
数据结构的基础:链表(所以语言实现要有指针)
指针的重要性:
指针是C语言的灵魂
定义:
内存单元的编号
指针:
指针就是地址,地址就是指针
指针变量是存储指针的变量
int a[5]={0};
3[a]与a[3]的效果是相同的,3只是偏移地址,而a指向数组的的第一个元素。
所有的指针只占四个字节
结构体:
动态内存的分配和释放
只能通过地址(指针)来修改实参的值
指向指针的指针
int i=10;
int *p=&i;
void f(int *p)
{
.....
} //修改指针指向的变量的值
void f(int **p)
{
.....
} //修改指针变量的值
4.动态内存分配概述
malloc :
int len;
printf("请输入你需要分配的的数组长度:len =");
scanf("%d",len);
int *pArr=( int * )malloc( sizeof(int) * len ); // 只返回第一字节的地址
pArr[1]=10; //a[1]=4;
*pArr=4; //类似于 a[0]=10;
free(pArr); //把pArr所代表的动态的分配的20个字节内存释放
5.跨函数使用内存
函数调用时分配的内存在函数调用完成之后就被释放了,如果想使用调用过的函数的内存,就不能依靠静态内存分配,而要使用动态内存分配,动态内存分配在调用函数过后并不会被释放,只有作者通过手工 free() 进行释放。
内存泄露:内存忘记释放越用越少。(系统越用越慢)
应用:一个函数创建链表,另一个函数使用链表,用的也是这个“跨函数使用内存”。
6.数据结构复习
数据结构 = 个体的存储(数据) + 个体关系的存储(数据结构)
解决一个问题(模拟一个问题) = 一个个不可再分的个体 + 个体与个体之间的关系 + 解决问题的算法
算法 = 对数据的操作方式(解题的方法和步骤)
对于不同的数据存储结构,操作数据的方式(算法)是不一样的。
7.结构体的使用概述
struct Student
{
int sid;
char name[200];
int age;
};
struct Student st; //已经分配好了结构体变量的空间
struct Student st ={1000,"zhangsan",20}; // struct Student 是变量名,st 是变量
printf("%d %s %d\n",st.sid,st.name,st.age); //结构体变量的名字加点访问结构体变量成员
为什么出现结构体:很多事物有着很多属性,一个学生的属性所需要的数据类型有很多,所以要用不同的数据类型组成一个新的数据类型。(普通的基本类型无法满足复杂数据的要求)
指向结构体的指针:
struct student *pst;
pst =&st;
pst->sid=99; // pst->sid 等价于(*pst).sid 等价于 st.sid
如何使用结构体:
两种方式:
struct Student st ={1000,"zhangsan",20};
struct Student *pst=&st;
1. st.sid
2.pst->sid //pst所指向的结构体变量中的Sid成员
注意事项:
结构体变量不能加减乘除,但能够相互赋值
普通结构体变量和结构体指针变量作为函数传参的问题
用形参的方式传递参数,耗费空间和时间,形参传递时直接在内存中找到一块临时空间,把变量复制进去,函数完成之后在回收内存空间
8.链表的重要性
链表承接了,树和图的基础。
9.typedef (给数据类型取一个新的名字)
typedef int zheng; //为int类型再取一个名字;zheng 等价于 int
typedef struct Student
{
int sid;
char name[100];
char sex;
}ST; // 为Student结构体类型在定义一个新名字;
typedef struct Student
{
int sid;
char name[100];
char sex;
}* PST; // PST 相当于struct Student *
typedef struct Student
{
int sid;
char name[100];
char sex;
}*PST,ST; //同时取两个名字
连续存储数组的算法演示
模块一:线性结构【把所有的节点(数组的元素)用一根直线穿起来】
连续存储 [数组]
离散存储 [链表]
线性结构的常见应用之一: 栈
线性结构的常见应用之一:队列(和时间有关的操作)
范型:存储不一样,操作也一样。
10.链表的定义:
离散存储【链表】:
n个结点离散分配
彼此通过指针相连接
每个节点只有一个后续节点和前驱结点,首节点(第一个有效的节点)没有前驱节点,尾节点(最后一个有效的节点)没有后续节点。
头结点:(第一个有效节点之前的节点,头结点不存放有效数据)方便对链表的操作(增删改查)头结点的数据类型与后面每一个节点的数据类型是一样的
头指针:指向头节点的指针变量
尾指针:指向尾节点的指针变量
11.链表的分类:
单链表:
双链表:每个节点有两个指针域(尾节点有一个指针区域)
循环链表:能通过任何一个节点能找到其他所有节点
非循环链表:
12.非循环单链表插入节点伪算法
算法:遍历;查找;清空;销毁;求长度;排序;
插入节点:r = p->pNext; p->pNext = q; q->pNext = r;
删除节点:p->pNext=p->pNext->pNext;(这样写容易造成内存泄漏)
正确写法:
r=p->pNext;
p->pNext=p->pNext->pNext;
free(r);
每个链表节点的数据类型该如何表示的问题
节点:每个节点至少包含两个部分(数据 和 指针),结构体的某个成员指向他本身了。
typedef struct Node
{
int data; //数据域
struct Node *pNext; //指针域
}NODE,*PNODE;
13.链表的创建和链表的遍历算法
#include
#include
#include
typedef struct Node
{
int i;
struct Node* pNext;
}NODE,*PNODE;
PNODE creat_list(void);
void trval_list(PNODE pHead);
int main(void)
{
PNODE pHead=NULL;
pHead=creat_list();
trval_list(pHead);
return 0;
}
PNODE creat_list(void) //创建链表
{
int len; //有效节点的个数
int i;
int val; //用来临时存放用户输入节点的值
PNODE pHead=(PNODE)malloc(sizeof(NODE));
if(NULL==pHead)
{
printf("分配失败,程序终止!\n");
exit(-1);
}
PNODE pLast=pHead;
pLast->pNext=NULL;
printf("请输入您需要的节点个数:len=");
scanf("%d",&len);
for(i=0;ii =val;
pNew->pNext=NULL;
pLast->pNext=pNew;
pLast=pNew;
}
return pHead;
}
void trval_list(PNODE pHead) // 遍历链表
{
PNODE p=NULL;
p=pHead->pNext;
while(p!=NULL)
{
printf("%d\n",p->i);
p=p->pNext;
}
return; //不返回值,但是告诉别人这个已经结束了
}
14.通过链表的排序算法,讨论什么是算法,什么是范型
算法:
狭义的算法:是与数据的存储方式密切相关的。
广义的算法:与数据额存储方式无关
范型:(要学习 C++中的模板与函数重载)
利用某种技术达到的效果:
不同的存储方式,执行的操作是一样的。(造成一种假象,让人感觉都是一样的)
重载:赋予一个事物不同的含义
排序函数:
void sort_list(PNODE pHead)
{
int i, j, t;
int len = length_list(pHead);
PNODE p, q;
for (i=0,p=pHead->pNext; ipNext)
{
for (j=i+1,q=p->pNext; jpNext)
{
if (p->data > q->data) //类似于数组中的: a[i] > a[j]
{
t = p->data;//类似于数组中的: t = a[i];
p->data = q->data; //类似于数组中的: a[i] = a[j];
q->data = t; //类似于数组中的: a[j] = t;
}
}
}
return;
}
15.学习算法的一些感想
学习算法:有些东西想不出来,把答案的程序看懂。(流程 语句的功能 试数)