数据结构(C语言第2版)----时间复杂度和单链表

简介: 数据结构(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);也就是线性表示。


看下面的这个表。


image.png

一些常见的算法


  • 起泡排序算法(冒泡法)


  思路:就是一列数据,拿着第一个数据开始往后面比较,若大于则交换,否则不交换,这样就把其值按照从小到大或者从大到小的顺序来排序。这里需要一个临时变量保存值。


#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内部主要以顺序存储和链式存储来表示数据元素在逻辑上的相邻关系。链式存储结构的特点是逻辑上相邻接的数据元素在存储地址上不一定相邻接,数据元素逻辑上的相邻关系是通过指针来描述的,常用它来描述树状结构和图状结构在计算机内部的存储。


     数据类型就是一个值的集合和定义在这个值集上的一组操作的总称。

 

思维导图:第一次使用感觉还不错。就感觉流程图一样但是给人感觉不一样,很直观,没有什么冗余在里面。



679140-20160805150710450-646037893.png

679140-20160805150714543-1629117329.png


了解线性表


    线性表是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");
}






目录
相关文章
|
2月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
68 1
|
2月前
|
存储 算法 搜索推荐
【趣学C语言和数据结构100例】91-95
本文涵盖多个经典算法问题的C语言实现,包括堆排序、归并排序、从长整型变量中提取偶数位数、工人信息排序及无向图是否为树的判断。通过这些问题,读者可以深入了解排序算法、数据处理方法和图论基础知识,提升编程能力和算法理解。
66 4
|
2月前
|
存储 机器学习/深度学习 搜索推荐
【趣学C语言和数据结构100例】86-90
本文介绍并用C语言实现了五种经典排序算法:直接插入排序、折半插入排序、冒泡排序、快速排序和简单选择排序。每种算法都有其特点和适用场景,如直接插入排序适合小规模或基本有序的数据,快速排序则适用于大规模数据集,具有较高的效率。通过学习这些算法,读者可以加深对数据结构和算法设计的理解,提升解决实际问题的能力。
54 4
|
2月前
|
存储 算法 数据处理
【趣学C语言和数据结构100例】81-85
本文介绍了五个经典算法问题及其C语言实现,涵盖图论与树结构的基础知识。包括使用BFS求解单源最短路径、统计有向图中入度或出度为0的点数、统计无向无权图各顶点的度、折半查找及二叉排序树的查找。这些算法不仅理论意义重大,且在实际应用中极为广泛,有助于提升编程能力和数据结构理解。
56 4
|
2月前
|
算法 数据可视化 数据建模
【趣学C语言和数据结构100例】76-80
本文介绍了五种图论算法的C语言实现,涵盖二叉树的层次遍历及广度优先搜索(BFS)和深度优先搜索(DFS)的邻接表与邻接矩阵实现。层次遍历使用队列按层访问二叉树节点;BFS利用队列从源节点逐层遍历图节点,适用于最短路径等问题;DFS通过递归或栈深入图的分支,适合拓扑排序等场景。这些算法是数据结构和算法学习的基础,对提升编程能力和解决实际问题至关重要。
58 4
|
2月前
|
存储 算法 vr&ar
【趣学C语言和数据结构100例】71-75
本文介绍了五个C语言数据结构问题及其实现,涵盖链表与二叉树操作,包括按奇偶分解链表、交换二叉树左右子树、查找节点的双亲节点、计算二叉树深度及求最大关键值。通过递归和遍历等方法,解决了理论与实际应用中的常见问题,有助于提升编程能力和数据结构理解。
50 4
|
2月前
|
存储 算法 C语言
【趣学C语言和数据结构100例】66-70
本书《趣学C语言和数据结构100例》精选了5个典型的数据结构问题及C语言实现,涵盖链表与数组操作,如有序集合的集合运算、有序序列表的合并、数组中两顺序表位置互换、三递增序列公共元素查找及奇偶数重排。通过详细解析与代码示例,帮助读者深入理解数据结构与算法设计的核心思想,提升编程技能。
39 4
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
86 5
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
79 1
|
2月前
|
存储 机器学习/深度学习 算法
【趣学C语言和数据结构100例】61-65
本文介绍了五个关于C语言和数据结构的经典问题及其实现方法,涵盖查找链表共同后缀、删除重复节点、重新排列链表元素、合并有序链表以及特定条件下的链表排序。每个问题通过具体的算法设计,不仅展示了链表操作的灵活性,还强调了效率优化的重要性。通过这些问题的探讨,读者可以深入理解链表的基本操作和高级应用,提升解决实际问题的能力。
62 4

热门文章

最新文章