欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构学习笔记

程序员文章站 2022-05-01 10:55:26
...

1.衡量算法的标准:
时间复杂度:大概程序执行的次数,而非执行的时间
空间复杂度:算法执行过程中大概所占用的最大内存
难易程度
健壮性

 

2.int *p  //p是个指针变量,int *表示该P变量只能存储int类型变量的地址

 

3.地址:内存单元的编号,内存是可以被cpu直接访问的,内存的编号是不能重复的,内存的基本划分单位是字节

 

CPU--地址线(可以确定对哪个地址进行操作)
控制线(控制读和写)
数据线(数据传输)

 

4.指针就是地址,地址就是指针。
5.指针变量就是存放内存单元地址的变量
6.指针的本质就是一个受限的非负整数


分类:
1.基本类型的指针
int * p//p是个指针变量,int *表示该p变量只能存储int类型的指针变量地址

int *p;
int i =10;
p=&i;

 

如果*p就是i,可以互换。任何一个改变都会变化
p保存i的地址,修改p的值不改变i的值
*p指向一个不确定的单元的值

 

2.指针与数组的关系
int a[5]={0,1,2,3,4,5};
printf("%p\n",a+1);  0012FF70  //指向第二个元素
printf("%p\n",a+2); 0012FF74  //指向第三个元素
printf("%d\n",*a+3); 4  //等价于a[0]+3 

 

一维数组名是个指针变量
它存放的是以维数组第一个元素的地址,他的值不能被改变,一唯数组名指向的是数组的第一个元素
a-->a[0]
所以下标和指针的关系:a[i]==*(a+i)
只要是数组物理空间一定是连续的

 

指针变量的运算:
指针变量不能相加,不能相乘相除
如果两个指针属于同一个数组,就可以相减
p+i的值是p+i*(p所指向的变量所占的字节数)
p-i的值是p-i*(p所指向的变量所占的字节数)
p++==p+1
p--=p-1

 

int 4个字节   一个字节是8位,一个字节是一个地址
double 8个字节

 

%p实际就是以十六进制输出

 

所有的指针变量只占4个子节  用第一个字节的地址表示整个变量的地址

例1:

int main(void){
	int i =10;
	f(&i);
	printf("i=%d\n",i);  //i=99
	return 0;
}
void f(int * p){
	*p=99;
}

 

例2:

int main(void){
	int i =9;
	int * p=&i;
	printf("%p\n",p);//p的地址已经改变
	f(&p);//要改变他在内存的值就把地址放进去
	printf("%p\n",p);
	return 0;
}
void f(int ** q){
	*q=(int *)0xFFFFFFFF
}

 

结构体:
1.为什么会出现结构体

#include<stdio.h>
#include<string.h>
struct Student{
 int sid;
 String name;
 int age;//只有属性没有方法,功能相对较弱,类更能完整的表现失误,结构体就是类的一个过渡
}

 为了表现一些复杂的数据,而普通的基本数据类型无法满足要求。所以会出现

 

2.什么叫结构体
结构体是用户根据用户实际需要和自己定义的复合数据类型

 

3.如何使用结构体

int main(void){
	struct Student st={1000,"zhangsan",20};
	printf("%d %s %d \n",st.sid,st.name,st.age);//字符串输出是%s	
		
	st.sid=99;
	strcpy(st.name,"lisi");//字符串要这样赋值
	st.age=22;
	printf("%d %s %d \n",st.sid,st.name,st.age);
	return 0;
}

int main(void){
	struct Student  st={1000,"zhangsan",20};
	struct Student * pst;
	pst=&st;
	pst->sid=99;//pst->sid等价于(*pst).sid  第一种方式:st.sid 2.ppst->sid
	return 0;
}

 4.注意事项
结构体变量不能加减乘除,但是可以相互复制
普通结构体变量和结构体指针变量作为函数传参的问题

 

//把第一个字节转化成整形,就可以把pArr当成数组使用
int * pArr=(int *)malloc(sizeof(int)* len)
*pArr=4; //类似于a[0]=4
pArr[1]=10;//类似于a[1]=10
free(pArr)//释放内存

 

下程序中能够调用函数fun(),使main函数中的指针变量p指向一个合法的整形单元:
跨函数使用内存的例子

main(){
int *p;
fun(&p);
...
}
int fun(int **q){
*q=(int *)malloc(4);
}

 

数据的存储不一样,数据的操作就不一样了

数据结构=个体的存储+个体的关系存储
算法=对存储数据的操作

 

数据结构:
1.数据的存储:
线性结构:把所有的节点用一根直线穿起来
连续存储【数组】:类型大小相同。
 数组的优缺点:
  
离散存储【链表】
 链表的优缺点:
  
线性结构最常见的应用:1.栈,队列
非线性结构存储

2.用c实现java中ArrayList功能

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
//定义了一个数据类型,struct Arr的类型
struct Arr{
	int *pBase;//存储的是数组第一个元素的地址
	int len;//数组所能容纳的最大元素的个数
	int cnt;//当前数组有效元素的个数
}

void init_arr(struct Arr * pArr,int length);
bool append_arr(struct Arr * pArr,int val);//追加
bool insert_arr();
bool delete_arr();
int get();
bool is_empty(struct Arr * pArr);
bool is_full(struct Arr * pArr);
void sort_arr();
void show_arr(struct Arr * pArr);
void inversion_arr();

int main(void){
	struct Arr arr;
	int_arr(&arr,6);
	show_arr(&arr);
	append_arr(&arr,1);
	return 0;	
}
void int_arr(struct Arr * pArr,int length){
	pArr->pBase=(int *)maclloc(sizeof(int)* length);
	if(NULL==pArr->pBase){
		printf("动态内存分配失败")
		exit(-1);//终止整个程序
	}else{
		pArr->len=length;
		pArr->=0;
	}
	return;
}
bool is_empty(struct Arr * pArr){
	if(0==aArr->cnt){
		return true;
	}else
	return false;
}
void show_arr(struct Arr * pArr){
	if(is_empty(pArr)){//如果数组为空,提示
		printf("数组为空");	
	}else{
		for(int i=0;i<pArr->len;==i){
			printf("%d",pArr->pBase[i]);//int *类型
		}
	}
bool is_full(struct Arr * pArr){
	if(pArr->cnt==pArr->len)
	return true
	else
	return false
}
bool append_arr(struct Arr * pArr,int val){
	//满了就返回false
	if(is_full(pArr))
	return false;
	//不满就追加
	pArr->pBase[pArr->cnt]=val;
	(pArr->cnt)++;
	return true;
}
}

 

typedef int zhangsan;  //zhangsan等价于int

typedef struct Student{
	int sid;
	char name[100];
	char sex;
}ST;

 

//链表节点的数据类型
struct Node{
	int data;//数据域
	struts Node * pNext;//指针域
}NODE,* pNODE;

 链表分类:
单链表 
双链表:每一个节点有两个指针域,双向指
循环链表:能通过任何一个节点找到所有的节点
非循环链表

 

泛型:利用某种技术达到的效果是:不同的存数方式,执行的操作是一样的

算法:狭义的算法是与数据的存数方式密切相关
广义的算法是与数据的存储方式无关

离散存储[链表]
优点:空间没有限制  插入删除元素很快
缺点:存取速度慢
连续存储【数组】:
优点:
存取速度快
缺点:事先必须知道数组的长度、 插入删除元素很慢、空间通常有限制、需要大块的连续内存


定义:一种可以实现“先进后出”的存储结构
栈类似于箱子
应用:函数调用,中断,表达式求值,内存分配,缓冲处理,迷宫

 

1.栈程序的演示:

#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
typedef struct Node{
	int data;
	struct Node * pNext;
}NODE,* PNODE;
typedef struct Stack{
	PNODE pTop;
	PNODE pBottom;
}STACK,* pSTACK;

void init(pSTACK);
void push(pSTACK,1);
void push(pSTACK);

int main(void){
	STACK S;//STACK等价于struct Stack
	init(&S);//目的是造出一个空栈
	push(&S,1);
	push(&S,2);
	traverse(&S);//遍历输出
	return 0;
}

void init(pSTACK pS){
	pS->pTop=(PNODE)malloc(sizeof(NODE));
	if(NULL==pS->pTop){
		printf("动态内存分配失败");
		exit(-1);
	}
	else{
		pS->pBottom=ps->pTop;
		pS->pTop->pNext=NULL;
	}
}

void push(pSTACK pS,int val){
	PNODE pNew==(PNODE)malloc(sizeof(NODE));

	pNew->data=val;
	pNew->pNext=pS->pTop;
	pS->pTop=pNew;
}

void traverse(pSTACK pS){
	PNODE p=pS->pTop;
	while(p!=pS->pBottom){
		printf("%d",p->data);
		p=p->pNext;
	}printf("\n");
	return;
}

 

链表队列--用链表实现
静态队列--用数组实现
 静态队列通常都必须是循环队列

 

队头出,队为入,所以不论新增还是删除front和rear都会增加,所以静态队列必须是循环队列

队列空:font和rear相等就是空的

入队:r=(r+1)%队列的长度
出队:font=(font+1)%队列的长度

判断队列是否满(f和r值紧挨着):(rear+1)%数组长度==f 

递归:
一个函数自己直接或间接调用自己

举例:
1.求阶乘(1)n!=n*(n-1)!

#include<stdio.h>
int main(void){
	int val;
	int i,mult=1;s
	printf("请输入一个数字";)
	printf("val=");
	for(i=1;i<=val;++i){
		mult=mult*1;
		printf(mult);
	}
}

 

2.递归求阶乘(2)

long f(long n){
	if(1==n)
	return 1;
	else
	return f(n-1)*n
}
int main(void){
	printf("%d\n",f(3));
	return 0;
}

 

3.递归求和

long sum(long n){
	if(1==n)
	return 1;
	else
	return n+sum(n-1);
}
int main(void){
	printf("%ld\n",sum(100));
	return 0;
}

 

函数的调用:
1.当一个函数在运行期间调用另一个函数时候,在运行被调函数之前,系统需要完成3件事情:
 将所有的实际参数,返回地址等信息传递给被调函数保存
 为被调函数的局部变量分配存储空间
 将控制转移到被调函数的入口
2.从被调函数返回主调函数之前,系统也要完成3件事情
 保存被调函数的返回结果
 释放被调函数所占用的存储空间
 依照被调用函数保存的返回地址将控制转移到调用函数

 

递归必须满足的3个条件:
 1.递归必须要有一个明确的终止条件
 2.该函数所处理的数据规模必须在递减
 3.这个转化必须是可解的
递归和循环式可以转换的
递归:1.易于理解2.速度慢占用存储空间大
循环:不易理解,速度快,存储空间小

线性结构:
每个节点只有一个前驱节点,每个节点只有一个后续节点
首节点没有前驱节点  尾节点没有后续节点

相关标签: 数据结构 指针