`
501311837
  • 浏览: 18359 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

数据结构学习笔记

阅读更多

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.速度慢占用存储空间大
循环:不易理解,速度快,存储空间小

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

分享到:
评论

相关推荐

    Java数据结构学习笔记

    ### Java数据结构学习笔记知识点详解 #### 一、数据结构与算法基础 1. **数据结构定义** - 数据结构是一门研究组织数据方式的学科,它与编程语言紧密相关,是实现高效程序设计的基础。 - 在软件开发中,合理选择...

    数据结构学习笔记基数排序 详细讲解

    数据结构学习笔记基数排序 详细讲解数据结构学习笔记基数排序 详细讲解数据结构学习笔记基数排序 详细讲解数据结构学习笔记基数排序 详细讲解数据结构学习笔记基数排序 详细讲解数据结构学习笔记基数排序 详细讲解...

    数据结构学习笔记排序算法:基数排序

    数据结构学习笔记排序算法:基数排序数据结构学习笔记排序算法:基数排序数据结构学习笔记排序算法:基数排序数据结构学习笔记排序算法:基数排序数据结构学习笔记排序算法:基数排序数据结构学习笔记排序算法:基数...

    算法与数据结构学习笔记

    这本"算法与数据结构学习笔记"涵盖了这两个核心概念的详细讲解,对于任何想要深入理解计算机科学原理、提高编程技能的人来说,都是一份宝贵的资源。 算法,简单来说,就是解决特定问题的步骤或指令集。它在计算机...

    考研数据结构学习笔记.doc

    "数据结构学习笔记" 本文档是一个关于数据结构学习笔记,涵盖了数据结构的基本概念、逻辑结构、物理结构、算法设计规范、算法时间复杂度分析、空间复杂度分析等方面的内容。下面是对每个知识点的详细解释: 一、...

    数据结构学习笔记.doc

    数据结构学习笔记 数据结构是一种组织和存储数据的方式,它包括数据的逻辑结构、存储结构和运算。数据结构的学习是计算机科学和信息技术的基础,它对计算机科学和信息技术的发展产生了深远的影响。 数据结构可以...

    数据结构学习笔记.zip

    本压缩包"数据结构学习笔记.zip"包含了丰富的资源,对于大学生来说,是深入理解数据结构的重要参考资料。 在数据结构的学习中,我们首先会接触到线性数据结构,如数组、链表、栈和队列。数组是最基础的数据结构,它...

    数据结构学习笔记.docx

    数据结构是计算机科学中的核心概念,...以上就是数据结构学习笔记的主要内容,涵盖了时间复杂度、空间复杂度、线性表、栈、队列、字符串、数组和矩阵等核心概念。理解并掌握这些知识对于深入学习计算机科学至关重要。

    数据结构学习笔记C版

    在C语言版本的数据结构学习笔记中,我们主要关注以下几个方面: 1. 数据和数据元素:数据是信息的载体,是计算机可以识别、存储和处理的对象。数据元素是数据的基本单位,它可以由一个或多个数据项组成,而数据项是...

    算法和数据结构学习笔记.zip

    在“算法和数据结构学习笔记.zip”这个压缩包中,很可能包含了丰富的资源,帮助大学生深入理解和掌握这一重要领域。 数据结构的学习通常分为几个关键部分: 1. **线性数据结构**:如数组、链表、栈和队列。数组是...

    算法数据结构学习笔记-C语言.zip

    "算法数据结构学习笔记-C语言.zip"这个压缩包很可能是为大学生提供的一份详细的学习资源,涵盖了数据结构的基础知识、常见算法以及相关的实践练习。 首先,我们要理解数据结构的基本概念,如数组、链表、栈、队列、...

Global site tag (gtag.js) - Google Analytics