• 结构之美:线性表的查找、插入与删除操作


    上一篇讲了线性表的定义与初始化,接下来需要了解一下线性表的一些基本操作。

    查找

    查找线性表是最基本的操作之一,比如根据序号查找元素的值,或者根据值查找该值是否在线性表中,如果在,那么序号是几等等。

    我们来看下面一段代码:
    01
    #define OK 1
    02
    #define ERROR 0
    03
    #define TRUE 1
    04
    #define FALSE 0
    05
    typedef int Status;          /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
    06
     
    07
    /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
    08
    /* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */
    09
    Status GetElem(SqList L,int i,ElemType *e)
    10
    {
    11
        if(L.length==0 || i<1 || i>L.length)
    12
                return ERROR;
    13
        *e=L.data[i-1];
    14
     
    15
        return OK;
    16
    }
    

    以上代码就是用来获得某一元素的操作。

    插入

    有了以上的基础,我们就能对顺序存储结构的插入与删除做一个讲解了。首先,我们来了解下插入操作。

    1. 如果插入的位置不合理,那么就抛出异常。
    2. 如果线性表长度大于等于数组长度,则抛出异常或者动态增加容量。
    3. 从最后一个元素开始向前遍历到第i个位置,分别将它们都向后移动一个位置。
    4. 将要插入的元素填入位置i处。
    5. 表长加1。
    01
    /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
    02
    /* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
    03
    Status ListInsert(SqList *L,int i,ElemType e)
    04
    {
    05
        int k;
    06
        if (L->length==MAXSIZE)  /* 顺序线性表已经满 */
    07
            return ERROR;
    08
        if (i<1 || i>L->length+1)/* 当i比第一位置小或者比最后一位置后一位置还要大时 */
    09
            return ERROR;
    10
     
    11
        if (i<=L->length)        /* 若插入数据位置不在表尾 */
    12
        {
    13
            for(k=L->length-1;k>=i-1;k--)  /* 将要插入位置之后的数据元素向后移动一位 */
    14
                L->data[k+1]=L->data[k];
    15
        }
    16
        L->data[i-1]=e;          /* 将新元素插入 */
    17
        L->length++;
    18
     
    19
        return OK;
    20
    }
    

    它是先往后挪一个位置,然后最后再插入进去。

    删除

    然后,我们一起看看删除操作。还是从思路开始说:

    1. 如果删除位置不合理,抛出异常
    2. 取出删除元素
    3. 从删除元素位置开始遍历到最后一个元素位置,分别将它们向前移动一个位置
    4. 表长减1.
    5. 01
      /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
      02
      /* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
      03
      Status ListDelete(SqList *L,int i,ElemType *e)
      04
      {
      05
          int k;
      06
          if (L->length==0)               /* 线性表为空 */
      07
              return ERROR;
      08
          if (i<1 || i>L->length)         /* 删除位置不正确 */
      09
              return ERROR;
      10
          *e=L->data[i-1];
      11
          if (i<l->length)                /* 如果删除不是最后位置 */
      12
          {
      13
              for(k=i;k<l->length;k++)/* 将删除位置后继元素前移 */
      14
                  L->data[k-1]=L->data[k];
      15
          }
      16
          L->length--;
      17
          return OK;
      18
      }
      19
      </l-></l->
      

      它是先把那个位置上的数提出来,然后向前挪。
    6. 分析上述插入和删除两段代码和更早的获取元素代码,我们可以发现,线性表的顺序存储结构,在存/读数据时,不管是哪个位置,时间复杂度O(1),而插入或删除时,时间复杂度都是O(n)。

      说完了顺序存储结构,我们可以总结下它的优缺点了,喜欢先听优点还是先听缺点呢?

      好吧,从优点开始说。当我们在使用线性表的时候,我们不需要为表中元素之间的逻辑关系而增加额外的存储空间,而且可以快速的存取表中任意位置的元素。接下来谈谈缺点。如我们所见,如果我们要插入或者删除的元素是在第一个位置,那么无疑的,我们需要移动大量的元素来完成这样的操作,而且限于线性表长度必须小于数组长度,如果我们需要插入大量数据,那么很难保证空间是否充足,而如果我们要删除大量数据的时候,无疑又会造成空间的浪费。

      001
      #include <stdio.h>
      002
      #include <stdlib.h>
      003
      #include <time.h>
      004
       
      005
      #define MAXSIZE 20      /* 存储空间初始分配量 */
      006
      typedef int ElemType;   /* ElemType类型根据实际情况而定,这里假设为int */
      007
      typedef struct
      008
      {
      009
          ElemType data[MAXSIZE]; /* 数组,存储数据元素,最大值为MAXSIZE */
      010
          int length;             /* 线性表当前长度 */
      011
      }SqList;
      012
       
      013
      //顺序表的初始化
      014
      SqList Init()
      015
      {   //构造一个空的线性表L,时间复杂度O(1)
      016
          SqList L;       //定义一个顺序表
      017
          L.length = 0;   //顺序表的长度为0
      018
          return L;       //返回空顺序表
      019
      }
      020
       
      021
      //顺序表的建立
      022
      SqList Create(SqList L)
      023
      {
      024
          int i;
      025
          srand((unsigned)time(NULL));
      026
          for(i=0; i < 10; i++)
      027
          {
      028
              L.data[i] = rand()%100;
      029
              L.length++;
      030
          }
      031
          return L;
      032
      }
      033
       
      034
      /* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
      035
      /* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */
      036
      ElemType GetElem(SqList L,int i)
      037
      {//
      038
          if(i < 1 || i > L.length)
      039
          {
      040
              printf("查找位置错误!
      ");//检查查询位置是否合法
      041
              return 0;
      042
          }
      043
          else
      044
              return L.data[i-1];
      045
      }
      046
       
      047
      //顺序表的插入
      048
      SqList SqListInsert(SqList L, int i, ElemType x)
      049
      {   //在顺序表中的第i个位置插入元素x
      050
          if(L.length == MAXSIZE)
      051
              printf("表已经满了
      ");//插入时,必须检查表是否已经满了。否则会出现溢出错误
      052
          else if(i < 1 || i > L.length)
      053
              printf("插入位置错误
      ");//判断插入位置的有效性
      054
       
      055
          int j;
      056
          for(j = L.length-1; j >= i - 1; j--)//第i个位置元素逐个后移
      057
              L.data[j+1] = L.data[j];
      058
          L.data[i-1] = x;                        //插入元素x
      059
          L.length++;                         //顺序表长度增1
      060
          return L;
      061
      }
      062
       
      063
      SqList SqListDelete(SqList L,int i)
      064
      {//删除顺序表中的第i个位置的元素
      065
          if(i < 1 || i > L.length)
      066
              printf("删除位置错误
      ");     //检查删除位置是否合法
      067
          int j;
      068
          for(j = i-1; j < L.length; j++)
      069
              L.data[j] = L.data[j+1];        //将第i个位置之后的元素前移
      070
       
      071
          L.length--;                         //顺序表长度-1
      072
          return L;
      073
      }
      074
       
      075
      int main()
      076
      {
      077
          SqList nmList;
      078
          nmList = Init();
      079
          nmList = Create(nmList);
      080
          int find;
      081
          int found;
      082
          int pos;
      083
          ElemType value;
      084
          char opp;
      085
       
      086
          int i;
      087
          printf("顺序表初始化为:");
      088
          for(i=0; i < nmList.length; i++)
      089
          {
      090
              printf("%d ", nmList.data[i]);
      091
          }
      092
       
      093
          printf("
      1.查看顺序表 
      2.查找 
      3.插入 
      4.删除 
      0.退出 
      请选择你的操作:
      ");
      094
          while(opp != '0'){
      095
              scanf("%c",&opp);
      096
              //printf("
       1.查找 
       2.插入 
       3.排序 
       0.退出 
       请选择你的操作:
      ");
      097
              switch(opp){
      098
                  case '1':
      099
                      printf("
      查看顺序表:");
      100
                      for(i=0; i < nmList.length; i++)
      101
                      {
      102
                          printf("%d ", nmList.data[i]);
      103
                      }
      104
                      printf("
      ");
      105
                      break;
      106
                  case '2':
      107
                      printf("
      进入查找功能,请问需要查找第几个元素:");
      108
                      scanf("%d",&find);
      109
                      printf("%d",find);
      110
                      found = GetElem(nmList, find);
      111
                      printf("第%d个值为%d ", find, found);
      112
                      printf("
      ");
      113
                      break;
      114
                  case '3':
      115
                      printf("进入插入功能,请输入插入元素位置:");
      116
                      scanf("%d",&pos);
      117
                      printf("请输入插入元素的值:");
      118
                      scanf("%d",&value);
      119
                      nmList = SqListInsert(nmList,pos,value);
      120
       
      121
                      printf("
      插入元素后顺序表为:");
      122
                      for(i=0; i < nmList.length; i++)
      123
                      {
      124
                          printf("%d ", nmList.data[i]);
      125
                      }
      126
                      printf("
      ");
      127
                      break;
      128
                  case '4':
      129
                      printf("进入删除功能,请输入删除元素位置:");
      130
                      scanf("%d",&pos);
      131
                      nmList = SqListDelete(nmList,pos);
      132
       
      133
                      printf("
      删除元素后顺序表为:");
      134
                      for(i=0; i < nmList.length; i++)
      135
                      {
      136
                          printf("%d ", nmList.data[i]);
      137
                      }
      138
                      printf("
      ");
      139
                      break;
      140
                  case '0':
      141
                      exit(0);
      142
              }
      143
          }
      144
       
      145
      }
      



  • 相关阅读:
    SharePoint 2013 中的SQL Server 安全
    SharePoint 2013 的HTML5特性之响应式布局
    SharePoint 2013 一些小技巧
    SharePoint 2013 排错之"Code blocks are not allowed in this file"
    SharePoint 2013 创建搜索中心及搜索设置
    SharePoint 2013 使用PowerShell创建State Service
    SharePoint 2013 内容部署功能简介
    SharePoint 使用PowerShell恢复误删的网站集
    SharePoint 自定义WebPart之间的连接
    linux之misc及使用misc创建字符设备
  • 原文地址:https://www.cnblogs.com/didi520/p/4165489.html
Copyright © 2020-2023  润新知