数据结构(C语言第2版)----时间复杂度和单链表
马上要到校招了,复习下相关的基础知识。
时间复杂度是什么?
官方解释:
算法的执行时间需要依据算法所编制的程序在计算机上于运行时所消耗的时间来度量。在算法中可以使用基本的语句的执行次数作为算法的时间复杂单位,可以认为一个特定算法时间性能只依赖于问题的规模(n),或者说它是一个特定算法时间性能只依赖于问题n的一个函数f(n),当问题规模n趋近于无穷大时的时间量级就称为算法的渐近时间复杂性,简称时间复杂度。
其实说白了就是看这个程序可以执行多少步,看它是否有循环,最后在把值估计计算下就是时间复杂度了,
先看一个简单的类子;
#include "stdio.h"
int main(){ int i,s=0;
for(i=0;i<=n;i++){
s=s+i;
}
printf("%d\n",s);
return 0;
}
这只是一个for循环而已,那么它的时间复杂度是多少呢;可以将每一步的执行步骤写出来,都加起来,计算出其总的时间复杂度。这个时间复杂度是O(n);也就是线性表示。
看下面的这个表。
名称 | 时间复杂度T(n) | 说明 |
常量阶 | O(1) | 于问题规模无关的算法 |
线性阶 | O(n) | 相关的单循环 |
平方阶 | O(n*n) | 二重循环 |
对数阶 | O(log2^n) | 折半查找算法 |
复合阶 | O(nlog2^n) | 堆排序算法 |
一些常见的算法
- 起泡排序算法(冒泡法)
思路:就是一列数据,拿着第一个数据开始往后面比较,若大于则交换,否则不交换,这样就把其值按照从小到大或者从大到小的顺序来排序。这里需要一个临时变量保存值。
#include "stdio.h"
int main(){
int a[8]={1,3,1,2,34,4,5,6};
int i,j,temp=1; //temp作为临时变量
for(i=1;i<8;i++)
for(j=1;j<=8-i;j++){
if(a[j]>a[j+1]){
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
for(i=1;i<8;i++){
printf("%d,",a[i]);
}
printf("你好世界\n");
重点是内层循环的比较,也就是那里面的每一次交换值。时间复杂度为T(n)=O(n^2);
名词解释
数据元素是描述数据的基本单位;数据项是描述数据的最小单元;数据对象是数据的一个子集,数据结构是由数据和结构组成,也就是数据元素及数据元素之间关系的集合。相互之间有一种或多种特定关系的数据元素的集合。
逻辑结构:是以抽象的数学模型来描述数据结构中数据元素之间的逻辑关系,使用二元组来表示;
物理结构:叫做存储结构,是数据结构在计算机内的存储表示,也是内存映像;
在PC内部主要以顺序存储和链式存储来表示数据元素在逻辑上的相邻关系。链式存储结构的特点是逻辑上相邻接的数据元素在存储地址上不一定相邻接,数据元素逻辑上的相邻关系是通过指针来描述的,常用它来描述树状结构和图状结构在计算机内部的存储。
数据类型就是一个值的集合和定义在这个值集上的一组操作的总称。
思维导图:第一次使用感觉还不错。就感觉流程图一样但是给人感觉不一样,很直观,没有什么冗余在里面。
了解线性表
线性表是n个数据元素a1,a2,…an组成的有限序列,记为L=(a1,a2…an);若n=0,则表示空表;同一个数据线性表中的数据元素必须具有相同的属性,即属于同一数据对象。
顺序表就是把线性表中的数据元素按其逻辑顺序依次存储在物理地址上也相邻的存储单元中,这种存储结构称为顺序结构存储,用顺序存储结构表示顺序表;顺序表的存储结构是一种随机存取的存储结构。
/*
01---顺序表的存储
*/ //表的定义
typedef int ElemType;
#define INITSIZE 100; //初始分配量
//定义了结构体
typedef struct{
ElemType *data; //数据域
int length; //长度
int listsize; //当前的存储容量
} sqlist; //为顺序表的类型名 //初始化操作
void initlist(sqlist *L){
L->data=(ElemType *)malloc(sizeof(ElemType)*INITSIZE); //动态申请存储空间
L->length=0;
L->listsize=INITSIZE;
}
//求表长操作
int getlen(sqlist *L){
return(L->length);
}
//取出数据元素
int getelem(sqlist *L,int i,ElemType *e){
if(i<1||i>L->length)return 0;
*e=L->data[i-1]; //相当与数组一样,下标差一位。
return 1;
}
//元素定位操作
int locate(sqlist *L,ElemType x){
int i=0;
while(i<L->length){
if(L->data[i]==x)
return i+1;
else
i++;
}
return 0;
}
//插入操作
int insert(sqlist *L,int i,ElemType x){
int j;
if(i<1||i>L->length+1)return 0;
if(L->length==L->listsize){
L->data=(ElemType *)realloc(L->data,(L->listsize+1)*sizeof(ElemType));
L->listsize++;
}
for(j=L->length-1;j>=i-1;j--){
L->data[j+1]=L->data[j]; //将所有的元素后移一位。
L->data[i-1]=x; //将元素插入i位置处。
L->length++; //长度加1;
return 1;
}
}
//删除元素
int delete(sqlist *L,int i,ElemType *e){
int j;
if(i<1||i>L->length)return 0;
*e=L->data[i-1];
for(j=i;j<L->length;j++){
L->data[j-1]=L->data[j];
L->length--;
}
}
//输出操作
void list(sqlist *L){
int i;
for(i=0;i<L->length;i++)
printf("%5d",L->data[i]);
printf("\n");
}
了解链表
顺序表在插入删除时需要移动大量的数据,这样导致内存消耗大,时间长,至此发明了链表来处理这种情况,使用链表可以指定在那里插入数据,不会移动所有的元素.只是指针的变化.当然这里也有缺点,只能进行顺序的存取,不行随机存取.
对于链表我们在内存中可以不按照顺序存储,只需要就将其指针对应起来,通过指针就可以找到所有的存储地点 。
- 单链表:只有两个区域,数据区和指针区,且有一个 头指针,最后一个数据与为NULL,所有的结点通过指针连接起来而组成链表。由于每个结点只包含一个指针域,所以称为单链表;
/*
单链表:
*/
typedef int ElemType;
typedef struct node{
ElemType data; //数据域
struct node * Next; //指针域
}slink; //结构体名 //建立单链表
slink *creslink(int n){
slink *head,*p,*s;
int i;
p=head=(slink *)malloc(sizeof(slink)); //创建头节点
for(i=1;i<=n;i++){
s=(slink *)malloc(sizeof(slink));
scanf("%d",&s->data);
p->Next=s;
p=s;
}
p->Next=NULL; //尾结点置空;
return head;
}
//求链表长度 ----使用n做累加值,求其链表的长度;
int getlen(slink * head){
slink *p;
int n;
p=head->Next;n=0;
while(p!=NULL){
n++;
p=p->Next;
}
return n;
}
//取元素操作
int getelem(slink *head,int i,ElemType *e){
slink *p;
int j;
if(i<1)return 0;
p=head->Next;j=1;
while(p!=NULL&&j<i){ //计算取出那个位置的值,也就是将P指定到位置。
p=p->Next;j++;
}
if(p==NULL)
return 0;
*e=p->data;
return 1;
}
//定位操作
slink * locate(slink *head,ElemType x){
int i;
slink *p;
p=head->Next;i=1;
while(p!=NULL&&p->data!=x){ //确定x的位置,将指针P抛出;
p=p->Next;i++;
}
return p;
}
//删除操作
int delete(slink * head,int i,ElemType *e){
slink * p,* q;
int j;
if(i<1) return 0;
p=head;j=0;
while(p->Next!=NULL&&j<i-1){ //确定出i的位置,
p=p->Next;j++;
}
if(p->Next==NULL)return 0;
q=p->Next; //删除元素,这里的最重要;
p->next=q->next;
*e=q->data;
free(q); //释放删除的元素空间
return 1;
} //插入元素
int insert(slink *head,int i,ElemType x){
slink *p,*q;
int j;
if(i<1)return 0;
p=head;j=0;
while(p!=NULL&&j<i+1){
p=p->Next;j++;
}
if(p==NULL)return 0;
q=(slink *)malloc(sizeof(slink)); //申请空间
q->data=x;
q->Next=p->Next; //相当于头插法;
p->Next=q;
return 1;
}
//输出操作
void list(slink *head){
slink *p;
p=head->Next;
while(p!=NULL){
printf("%4d",p->data);
p=p->Next;
}
printf("\n");
}
数据结构(C语言第2版)----时间复杂度和单链表的更多相关文章
- 数据结构与算法分析——C语言描述 第三章的单链表
数据结构与算法分析--C语言描述 第三章的单链表 很基础的东西.走一遍流程.有人说学编程最简单最笨的方法就是把书上的代码敲一遍.这个我是头文件是照抄的..c源文件自己实现. list.h typede ...
- 数据结构(c语言第2版)-----了解链表,栈,队列,串
关于链表我觉得这都是最基本的东西,但是不常见,在实际的应用中很少的使用,了解它会用就OK,不需要研究的那么深,除非做那种内存压缩,存储方面工作. C语言中动态申请空间 malloc() q=(dlin ...
- 用O(1)的时间复杂度删除单链表中的某个节点
给定链表的头指针和一个结点指针,在O(1)时间删除该结点.链表结点的定义如下: struct ListNode { int m_nKey; ListNode* m_pNext; }; 函数的声明如下: ...
- 数据结构(C语言第2版)-----数组,广义表,树,图
任何一个算法的设计取决于选定的数据结构,而算法的实现依赖于采用的存储结构. 之前线性表的数据元素都是非结构的原子类型,元素的值是不可再分的.下面学习的这两个线性表是很特殊的,其中数据元素本身也可能是一 ...
- 数据结构C语言实现系列——线性表(单向链表)
#include <stdio.h> #include <stdlib.h> #define NN 12 #define MM 20 typedef int elemType ...
- 《Java数据结构与算法》笔记-CH5-链表-2单链表,增加根据关键字查找和删除
/** * Link节点 有数据项和next指向下一个Link引用 */ class Link { private int iData;// 数据 private double dData;// 数据 ...
- 《Java数据结构与算法》笔记-CH5-链表-1单链表
/** * Link节点 * 有数据项和next指向下一个Link引用 */ class Link { private int iData;//数据 private double dData;//数据 ...
- c语言实现--不带头结点的单链表操作
1,不带头结点的单链表操作中,除了InitList(),GetElem(),ListInsert(),ListDelete()操作与带头结点的单链表有差别外,其它的操作基本上一样. 2,不带头结点单链 ...
- 数据结构C语言版 有向图的十字链表存储表示和实现
/*1wangxiaobo@163.com 数据结构C语言版 有向图的十字链表存储表示和实现 P165 编译环境:Dev-C++ 4.9.9.2 */ #include <stdio.h> ...
随机推荐
- MQTT协议简记
MQTT - MQ Telemetry Transport 轻量级的 machine-to-machine 通信协议. publish/subscribe模式. 基于TCP/IP. 支持QoS. ...
- 作业三:PSP耗时
请同学们参照教材<构建之法>2.3节表2-4 PSP2.1汇报自己在完成四则运算编程时候的时间分布,发布到博客上. 个人项目耗时情况分析 PSP Personal Software Pro ...
- [.net 面向对象编程基础] (9) 类和类的实例
[.net 面向对象编程基础] (9) 类和类的实例 类 ,顾名思义就是分类.类别的意思.我们要面向对象编程,就需要对不同的事物进行分类.类可以说是.net面向对象的核心. 类:就是具有相同的属性和功 ...
- Android Studio 1.0.1 + Genymotion安卓模拟器打造高效安卓开发环境
我们开发安卓大多是使用Eclipse和安卓SDK中自带的安卓模拟器.当然,Google早就推出了自己的安卓开发环境——Android studio,在不久前,Google发布了Android Stud ...
- 通过分析iframe和无阻塞脚本关系能让我们更懂iframe
在我上篇文章里,我提到一种使用iframe完成无阻塞脚本加载的方式,因为我对iframe的偏见很大,所以上篇文章里我没有展开讨论这个问题. 文章发表后有位网友问了我这样一个问题,下面是他问题的原文,如 ...
- C#Light 和 uLua的对比第二弹
上次的对比大家还有印象否,C#Light和ulua对比各有胜负 今天我们加入一个去反射优化,这是uLua没办法实现的优化,我们也就只能不要脸的胜之不武了 以原生执行同一测试时间为X1,数字越小的越快 ...
- Git 远程仓库搭建
大名鼎鼎的git就不多做介绍了,总之.我们使用git来作为项目的一个版本控制工具,多人开发的项目的时候会轻松很多. 安装git whthomas@whthomas:~/workplace/gitOne ...
- [备忘]删除SQL Server中无登录名的用户
这个问题通常会在还原虚拟主机的备份SQL文件后发生,原先在虚拟主机上的用户会被还原到本地,但是本地没有权限对其进行操作. SELECT N'ALTER AUTHORIZATION ON SCHEMA: ...
- 当pageIndex遇上pageNo
我们的项目程序里,由于赶项目进度,同时,大家缺乏相应的沟通,在服务层提供的接口里,涉及到分页查询的,有如下三种情形: l List<OrderInfo> GetOrderList(Ord ...
- Javascript隐式转换
乱想 javascript为什么需要隐式转换?如果没有会出现什么情况? 找了一圈没有看到关于这个的讨论,只好自己研究了,可能不一定正确,自行辨知. 郁闷就是郁闷在好好的,为什么要搞个隐式转换,一般来讲 ...