c数据结构-顺序表的实现以及时间复杂度的分析

线性表的顺序表示和实现

一:线性表的相关概念

1:定义

   由n(n>=0)个数据特性相同的元素构成的有限序列叫做线性。

2:特性

  • 数据元素的位序1开始
  • 除第一个恶元素之外,结构中的每个数据元素均有只有一个前驱
  • 除最后一个元素之外,结构中的每个数据元素均只有一个后继

二:顺序表介绍以及相关函数的介绍

1:定义

  顺序表示用一组地址连续的存储单元依次存储线性表的数据元素,这种表示也叫做线性表的顺序存储结构或者顺序映像

2:时间复杂度

  • 最好时间复杂度:最好情况下的时间复杂度
  • 最坏时间复杂度:最坏情况下的时间复杂度
  • 平均时间复杂度:算法在所有可能的情况下,按照输入实例以等概率出现时,算法计算量的 加权平均值

3:c语言中用到的函数介绍

sizeof实际上是获取了数据类型在内存中所占用的存储空间
下面是两种使用情况

  • 用于数据类型

    sizeof使用形式:sizeof(type)

    数据类型必须用括号括住。如sizeof(int)。

  • 用于变量

    sizeof使用形式:sizeof(var_name)或sizeof var_name

    变量名可以不用括号括住。如sizeof (var_name),sizeof var_name等都是正确形式。带括号的用法更普遍,大多数程序员采用这种形式。

    注意:sizeof操作符不能用于函数类型,不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。

malloc和free介绍
malloc()函数:其实就在内存中找一片指定大小的空间,然后将这个空间的首地址范围给一个指针变量,这里的指针变量可以是一个单独的指针,也可以是一个数组的首地址,这要看malloc()函数中参数size的具体内容。
free函数:释放内存空间

这两个函数都是在<stdlib.h>这个头文件中
malloc函数

  • 功能:在内存的动态存储区中分配一块长度为"size"字节的连续区域。函数的返回值为该区域的首地址。

  • 函数原型 :void malloc(int size);在c语言编写程序的具体使用过程中,void 类型可以强制转换为任何其它类型的指针。

  • 说明:如果分配成功则返回指向被分配内存的指针,否则返回空指针NULL。

  • 当内存不再使用时,应使用free()函数将内存块释放。

free函数

  • 调用形式: free(void*ptr);
  • 功能:释放ptr所指向的一块内存空间,ptr是一个任意类型的指针变量,它指向被释放区域的首地址。被释放区应是由malloc或calloc函数所分配的区域。

三:静态顺序表的实现

静态顺序表的缺点:大小是固定的(代码编写是就已经确定);

1:代码实现

#include "stdio.h"
#include "math.h"
#define MaxSize 10 //定义一个最大长度
//存储空间是静态的,顺序表的长度刚开始就确定了不能更改
typedef struct {
    int data[MaxSize];//用数组存放数据元素
    int length;       //顺序表的当前长度
}SqList;              //顺序表的类型定义
/**
 * 初始化一个顺序表
 */
 void InitList(SqList *L){
     //防止数组出现初始值错误
    for (int i = 0; i < MaxSize; ++i) {
        L->data[i]=0;
    }
    //顺序表的初始长度为0
    L->length=0;
 }
 /**
  * 创建一个线性表   --n是数组a[]的大小
  */
 int CreatList(SqList *L,int a[],int n){
     if(n>MaxSize){
         printf("空间不够,请重新分配空间\n");
         return 0;
     }
     //将数组a的值一个一个的赋值给data数组
     for (int i = 0; i <n; ++i) {
         L->data[i]=a[i];
     }
     //需要改变数组data的长度length值
     L->length=n;
     return 1;
 }
 /**
  * 修改顺序表中的元素  --index是位序,value是待修改的值并返回修改的值
  */
  int ModifyList(SqList *L,int index,int value){
      //首先对index进行判断
     if(index<1||index>L->length){
         return 0;
     }
     L->data[index-1]=value;
     return L->data[index-1];
  }
 /**
  * 打印顺序表中的元素
  */
 void PrintList(SqList *L){
     printf("顺序表的元素=[");
     for (int i = 0; i < L->length; ++i) {
         if(i< L->length-1){
             printf("%d,",L->data[i]);
         } else{
             printf("%d",L->data[i]);

         }
     }
     printf("]\n");
 }
 /**
  * 在表L的第i个位置上插入指定的元素e   --i指得是位序
  */
 int ListInsert(SqList *L,int i,int e){
     //首先进行位置判断
     if(i<1||i>L->length){
         return 0;
     }
     //判断是否超出定义数组的最大长度
     if(L->length>MaxSize){
         return 0;
     }
     //进行插入操作--将第i给位置以及后面的元素均往后移动一个单位
     for (int j =L->length; j >=i; j--) {
         L->data[j]=L->data[j-1];
     }
     //将待插入的元素给指定的位置
     L->data[i-1]=e;
     //数组的长度加1
     L->length++;
     return 1;
 }
 /**
  * 顺序表的删除--删除第index个元素(位序)并返回待删除的元素
  */
  int ListDelete(SqList *L,int index){
      //对index进行判断
      int e;//记录代删除的元素值
      if(index<1||index>L->length){
          return 0;
      }
      e=L->data[index-1];
     for (int i = index; i <L->length ; ++i) {
            L->data[i-1]=L->data[i];
     }
     //没删除一个元素后对数组的长度进行--操作
     L->length--;
     return e;
  }
 /**
  * 顺序表的查找  按位(位序)查找
  */
  int GetElem(SqList *L,int i){
     return L->data[i-1];
  }
  /**
   * 顺序表的查找  按值查找,并返回其位序
   */
   int LocateElem(SqList *L,int value){
      for (int i = 0; i < L->length; ++i) {
          if(L->data[i]==value){
              return i+1;
          }
      }
      return 0;
   }
   /**
    * 判空操作
    */
int ListEmpty(SqList *L){
       if(L->length==0){
           return 1;
       } else{
           return 0;
       }
   }


int  main(){
    SqList  L;        //声明一个顺序表
    InitList(&L);
    int n=6;
    int a[n];
    int e;//用来接收删除元素的值
    for (int i = 0; i < n; ++i) {
         a[i]=i;
     }
    if(CreatList(&L,a,n)==1){
        printf("创建数组成功!\n创建的");
    } else{
        printf("创建数组失败!\n");
    }
     PrintList(&L);

    if(ListInsert(&L,3,3)==1){
        printf("插入一个元素成功!\n");
    } else{
        printf("插入一个元素失败!\n");
    }
    PrintList(&L);
    printf("查找了元素为3的位序=%d\n", LocateElem(&L,3));

    if( (e=ListDelete(&L,4))!=0){
        printf("删除成功!\n");
        printf("删除了第四个元素,元素的值=%d\n删除之后",e);
        PrintList(&L);
    } else{
        printf("删除失败!\n");
    }

    if(ListEmpty(&L)==0){
        printf("顺序表的长度=%d\n",L.length);
    } else{
        printf("顺序表是空的!");
    }
     int modeifValue=L.data[2];
    if((e=ModifyList(&L,3,15))!=0){
        printf("修改前的第三个元素=%d\n",modeifValue);
        printf("修改成功!\n");
        printf("修改后的第三个元素=%d\n",e);
    }
    return 0;
}

2:时间复杂度的分析

  1. 插入函数时间复杂度分析
int ListInsert(SqList *L,int i,int e){
     //首先进行位置判断
     if(i<1||i>L->length){
         return 0;
     }
     //判断是否超出定义数组的最大长度
     if(L->length>MaxSize){
         return 0;
     }
     //进行插入操作--将第i给位置以及后面的元素均往后移动一个单位
     for (int j =L->length; j >=i; j--) {
         L->data[j]=L->data[j-1];
     }
     //将待插入的元素给指定的位置
     L->data[i-1]=e;
     //数组的长度加1
     L->length++;
     return 1;
 }
  • 最好时间复杂度:当插入元素的位置在静态数组的末尾,T(n)=O(1)

  • 最坏时间复杂度:当插入的元素在静态数组的开头,T(n)=O(n)

  • 平均时间复杂度: 假设新元素插入到任何一个位置的概率相同,即i 的值为1,2,3,…,length+1的概率都是p=1/n:

  • i=1,循环n次;

  • i=2,循环n-1次;i=3,i=4,…

  • i=n+1时,循环0次
    平均循环环次数=1/n*[n+(n-1)+…+2+1+0]=n/2
    T(n)=O(n)

  1. 删除操作时间复杂度分析
int ListDelete(SqList *L,int index){
      //对index进行判断
      int e;//记录代删除的元素值
      if(index<1||index>L->length){
          return 0;
      }
      e=L->data[index-1];
     for (int i = index; i <L->length ; ++i) {
            L->data[i-1]=L->data[i];
     }
     //没删除一个元素后对数组的长度进行--操作
     L->length--;
     return e;
  }
  • 最好时间复杂度:当删除元素的元素在静态数组的末尾,T(n)=O(1)

  • 最坏时间复杂度:当删除元素的元素在静态数组的开头,T(n)=O(n)

  • 平均时间复杂度: 假设删除任意元素的概率相同,即i 的值为1,2,3,…,length+1的概率都是p=1/n:

  • i=1,循环n-1次;

  • i=2,循环n-2次;i=3,i=4,…

  • i=n+1时,循环0次

平均循环环次数=1/n*[(n-1)+…+2+1+0]=n*(n-1)/2*1/n=(n-1)/2
T(n)=O(n)

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值