zoukankan      html  css  js  c++  java
  • 结构之美:线性表的查找、插入与删除操作

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

    查找

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

    我们来看下面一段代码:
    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
      }
      



  • 相关阅读:
    垃圾回收器总结(一)
    JVM 总结
    如何提升自己?
    堆和栈的区别
    Java 8 Streams API 详解
    说一说JVM双亲委派机制与Tomcat
    说一说switch关键字的奥秘
    深入了解 Java Resource && Spring Resource
    Spring 动态代理 之 but was actually of type 'com.sun.proxy.$Proxy14 Exception
    架构设计基础:单服务.集群.分布式,基本区别和联系
  • 原文地址:https://www.cnblogs.com/didi520/p/4165489.html
Copyright © 2011-2022 走看看