数据结构 第一章 绪论


第二章 线性表


基本概念

数据:所有能输入到计算机中并被计算机处理的符号总称。
数据元素:数据的基本单位,一个数据元素可由若干个数据项组成。
数据对象:性质相同的数据元素集合,数据的一个子集。
数据结构:一般和逻辑结构画等号,是相互之间存在一种或多种特定关系的数据元素的集合。

1.数据结构分类

数据结构可以分为线性结构和非线性结构。
数据结构可以分为集合、线性结构、树形结构和图状(网状)结构。

1.集合
2.线性结构
	数据元素之间一对一的关系
3.树形结构
	数据元素之间一对多的关系
4.图状(网状)结构
	数据元素之间多对多的关系

数据结构的形式定义为二元组 Data_Structure = (D,S),其中D是数据元素的有限集,S是D上关系的有限集。

数据元素的两种存储方式:顺序存储和链式存储。

顺序存储结构的数据元素占一片连续的空间,存储密度大,便于随机存取数据元素。
链式存储结构的优点是元素存放地址随意的,可连续可不连续。

2.抽象数据类型

抽象数据类型=数据对象+数据关系+基本操作

ADT 抽象数据类型名{
		数据对象:<数据对象的定义>
		数据关系:<数据关系的定义>
		基本操作:<基本操作的定义>
}ADT 抽象数据类型名

其中数据对象和数据关系的定义用伪码描述,基本操作的定义格式为:

基本操作名(参数表)
	初始条件:<初始条件描述>
	操作结果:<操作结果描述>

基本操作有两种参数:赋值参数只为操作提供输入值;引用参数以&开头,不仅为操作提供输入值,还将返回操作结果。

抽象数据类型的表示与实现

本节内容原文链接:抽象数据类型的表示与实现

1)数据结构的表⽰(存储结构)⽤类型定义(typedef)描述,例 typedef int Status //该语句的意思是在程序int的另⼀别名是Status,⽤Status表⽰int;
2)在代码中⽅法的形参表中,以&打头的参数是C++的引⽤,引⽤类型的变量,其值若在函数张发⽣变化,则变化的值会带回主调函数中;
3)程序中数据元素类型约定为ElemType。


#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<math.h>//其中定义OVERFLOW为3
#define OK 1
#define ERROR 0
typedef int Status;//Status表⽰函数的类型,其值是函数的结果状态码
typedef int ElemType;//定义抽象数据类型ElemType在本程序中为整型s In
//教科书内容
typedef ElemType *Triplet;//由InitTriplet分配3个元素存储空间,Triplet类型是ElemType类型的指针,存放ElemType类型的地址
Status InitTriplet(Triplet &T,ElemType v1,ElemType v2,ElemType v3){
	//操作结果:构造三元组T,依次置T的3个元素的初值为v1,v2和v3(教科书第12页)
	 T=(ElemType *)malloc(3* sizeof(ElemType));
	 if(!T) exit(OVERFLOW);//分配失败则退出
	 T[0]=v1,T[1]=v2,T[2]=v3;
	 return OK;
}
Status DestroyTriplet(Triplet &T){
	//操作结果:三元组T被销毁(教科书第12页)
	 free(T);//释放T所指的三元组存储空间
	 T=NULL;//T不在指向任何存储单元
	 return OK;
}
Status Get(Triplet T,int i,ElemType &e){
	 //初始条件:三元组T已存在,1≤i≤3。操作结果:⽤e返回T的第i元的值(教科书第12页)
	 if(i<1||i>3)//i不在三元组的范围之内
	  return ERROR;
	 e=T[i-1];//将三元组T的第i个元素的值赋给e
	 return OK;
}
Status Put(Triplet &T,int i,ElemType e){//此处的引⽤符&可加可不加,教科书上加了
	 //初始条件:三元组T已存在,1≤i≤3。操作结果:改变T的第i元的值为e(教科书第12页)
	 if(i<1||i>3)
	  return ERROR;
	 T[i-1]=e;
	 return OK;
}
Status IsAscending(Triplet T){//教科书第13页
	 //初始条件:三元组T已存在。操作结果;如果T的3个元素按升序排列,则返回1,否则返回0
	 return (T[0]<=T[1]&&T[1]<=T[2]);
}
Status IsDescending(Triplet T){
	 //初始条件;三元组T已存在。操作结果;如果T的3个元素按降序排列,则返回1,否则返回0
	 return (T[0]>=T[1]&&T[1]>=T[2]);
}
}
Status Max(Triplet T,ElemType &e){
	//初始条件:三元组T已存在。操作结果:⽤e返回指向T的最⼤元素的值(教科书第13页)
	 e=(T[0]>=T[1])?(T[0]>=T[2]?T[0]:T[2]):(T[1]>=T[2]?T[1]:T[2]);
	 return OK;
}
Status Min(Triplet T,ElemType &e){
	 //初始条件:三元组T已存在。操作结果:⽤e返回指向T的最⼩元素的值(教科书第13页)
	 e=(T[0]<=T[1])?(T[0]<=T[2]?T[0]:T[2]):(T[1]<=T[2])?T[1]:T[2];
	 return OK;
}
//测试函数
void PrintT(Triplet T)//依次输出三元组的值
{
 	printf("%d,%d,%d\n",T[0],T[1],T[2]);
}
void PrintE(ElemType e)//输出元素的值
{
	printf("%d\n",e);
}
void main(){
	Triplet T;
	ElemType m;
	Status i;
	i=InitTriplet(T,5,7,9);//初始化三元组T,其3个元素依次为5,7,9
	printf("调⽤初始化函数后,i=%d(1:成功)。T的3个值为",i);
	PrintT(T);//输出T的3个值
	i=Get(T,2,m);//将三元组T的第2个值赋给m
	if(i=OK){//调⽤Get()成功
		 printf("T的第2个值为");
		 PrintE(m);//输出m(=T[1])
	}
	i=Put(T,2,6);//将三元组T的第2个值改为6
	if(i==OK){//调⽤Put()成功
		 printf("将T的第2个值改为6后,T的3个值为");
		 PrintT(T);//输出T的3个值
	}
	i=IsAscending(T);//测试升序函数
	printf("调⽤测试升序的函数后,i=%d(0:否 1:是)\n",i);
	i=IsDescending(T);//测试降序的函数
	printf("调⽤测试降序的函数后,i=%d(0:否 1:是)\n",i);
	if(i=Max(T,m)==OK){
		 printf("T中的最⼤值为");
		 PrintE(m);//输出最⼤值m
	}
	if(i=Min(T,m)==OK){
		 printf("T中的最⼩值为");
		 PrintE(m);//输出最⼩值m
	}
	DestroyTriplet(T);//函数也可以不带返回值
	printf("销毁T后,T=%u\n",T);
}

运行结果:
运行结果

算法和算法分析

1. 算法

算法是指令的有限序列。具有以下特性:

(1) 输入:0或者多个外部输入

(2) 输出:至少一个外部输出,或者有多个输出

(3) 有穷性:在执行有限的步骤之后会自动结束而不会无限循环,可以理解为有限的步骤完成

(4) 确定性:每一步都有确定的含义,不会产生歧义的语法

(5) 可行性:每一步都是可行的、能够在有限的时间内完成

2. 算法设计的要求

(1) 正确性:算法需要满足具体问题的需求,并且对于精心选择的典型的,苛刻的机组输入数据能够得出满足规格说明的结果

解释:正确”大体可分为四个层次:a.程序不含语法错误;b.程序对于几组输入数据能够得出满足规格说明要求的结果;c.程序对于精心选择的典型、苛刻而带有刁难性的几组输入数据能够得出满足规格说明要求的结果;d.程序对于一切合法的输入数据都能产生满足规格说明要求的结果。(通常c层意义的正确性作为衡量一个程序是否合格的标准)。

(2) 可读性:不同人员能够阅读、正确理解、交流

(3) 健壮性:对于各种合法或者不合法的输入,能够合法、适当地做出反应或者进行处理

(4) 效率和低存储量需求:执行需要的时间、需要的最大的存储空间。

3. 算法效率的度量(时间复杂度和空间复杂度)

本节原文链接:002讲:算法和算法分析

时间复杂度T(n)=O(f(n))  //n:问题规模  f(n):基本操作的次数和  O(n):求数量级(阶)运算

下面是常见的时间算法举例
案例1: 常数阶 O(1)
在这里插入图片描述
第一个语句只有两句语句,所以花费的时间是:T(n)≈ O(1)
第二个语句有一个for循环,但是循环次数是固定的10次,所以T(n)= 10 ;则T(n)=11

案例2: 线性阶 O(n)
在这里插入图片描述
显而易见, 只有一个循环,循环条件是从1到n,所以T(n)= O(n)

例3 平方阶 O(n^2)
在这里插入图片描述
第一句和第二句时间都是1,第三句和第四句是n,第五句是n,第六句是nn,第七句是nn则所有的时间总和是:O(T)=1+1+n+n+n2+n2=2+2n+2n2=n2
直接找最复杂的语句块,一看就是循环的嵌套,循环的条件都是从1到n,所以可得:T(n)= O(N2)。

例4 对数阶 O(log2 n)
在这里插入图片描述
循环的条件是从1到n,但是每次循环i*=2,所以T(n)= O(log2 n)。

总结:
用常数1取代运行时间中的所有加法常数。
在修改后的运行次数函数中,只保留最高阶项。
如果最高阶项存在且不是1,则去除与这个项相乘的常数。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值