zoukankan      html  css  js  c++  java
  • 线性表学习之顺序表示

    原创博文,转载请注明出处

    线性表是一种逻辑结构,表示元素之间一对一的相邻关系。顺序表和链表是指存储结构,两者属于不同层面的概念,因此不要将其混淆。接下来我们学习:

    第一部分:线性表的顺序表示

    顺序表最主要的特点是可以进行随机存取,即通过首地址和元素序号可以在O(1)的时间内找到指定的元素。顺序表的存储密度高,每个节点只存储数据元素,但是插入和删除需要移动大量元素。

    插入、删除、查找的时间复杂度为O(n)

    综合应用 : 

               1、设计一个高效算法,将顺序表的所有元素逆置,要求算法的空间复杂度为O(1).

               算法思想:扫描顺序表L的前半部分元素,对于元素L.data[i](0<=i<=L.length/2),将其余后半部分对应元素L.data[L.length-i-1]进行交换。

    1  void Reverse(Sqlist &L){
    2         Elemtype temp;
    3         for(i=0;i<L.length/2;i++){
    4              temp=L.data[i];
    5              L.data[i]=L.data[L.length-i-1];
    6               L.data[L.length-i-1]=temp;
    7         }
    8  }
    View Code

               2、长度为n的顺序表L,编写一个时间复杂度为O(n),空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素。

               解法一:用K记录顺序表L中不等于x的元素个数(即需要保存的元素个数),边扫描L边统计k,并将不等于x的元素向前放置k位置上,最后修改L的长度。

    1 void del_x(Sqlist &L,Elemtype x){
    2        int k=0;
    3        for(i=0;i<L.length;i++)
    4             if(L.data[i]!=x){
    5                L.data[k]=L.data[i];
    6                k++;
    7            }      
    8       L.length=k;
    9 }
    View Code

              解法二: 用K记录顺序表中等于x的元素个数,边扫描L边统计k,并将不等于x的元素前移k个位置,最后修改L的长度。

              3、从有序 顺序表中删除其值在给定值s与t之间(要求s<t)的所有元素,如果s或t不合理或者顺序表为空则显示出错信息并推出运行.

              算法思想:先寻找值大于等于s的第一个元素(第一个删除的元素),然后寻找值>t的第一个元素(最后一个删除的元素的下一个元素),要将这段元素删除,则只需要直接将后面的元素前移即可。实现如下: 

     1 bool Del_s_t(sqList &L,ElemType s,ElemType t){
     2         int i,j;
     3         if(s<=t)||L.length==0
     4             return false;
     5         for(i=0;i<L.length&&L.data[i]<s;i++);
     6         if(i>L.length)
     7              return false;
     8         for(j=0;j<L.length&&L.data[j]<=t;j++);
     9         for(;j<L.length;i++,j++)
    10             L.data[i]=L.data[j];
    11         L.length=i;
    12         return true;
    13 }
    View Code

                那如果不是有序的怎么办呢?很简单,我们从前向后扫描顺序表L,用k记录下元素值在s到t之间元素的个数。对于当前扫描的元素,若其值不在s到t之间,则前移k个位置,替代原值,否则执行k++。由于这样每个不在s到t之间的元素仅移动一次,所以算法效率高。

              4、从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同。

                 算法思想:由于是有序表,所以值相同的元素一定在连续的位置上,判断后面的元素是否与前面的非重复有序表最后一个元素相同,如果相同则继续向后判断,如果不同则插入到前面的非重复有序表的最后 ,直到判断整个表尾为止。实现如下:

    1 bool Delete_Same(SeqList L){
    2         if (L.length==0)
    3               return false;
    4         int i,j;
    5         for(i=0,j=1;j<L.length;j++)
    6             if(L.data[i]<L.data[j])
    7                  L.data[++i]=L,data[j]
    8         L.length=i+1;
    9 }
    View Code

             5、将两个有序顺序表合并成一个新的有序顺序表,并有函数返回结果顺序表

                 算法思想:首先,按顺序不断取下两个顺序表表头较小的结点存入新的顺序表中。然后,看哪个表还有剩余,将剩下的部分加到新的顺序表后面。

     1 bool Merge(SeqList A, SeqList B ,SeqList &C){
     2         if(A.length+B.length>C.maxSize)
     3                return false;
     4         int i=0,j=0,k=0;
     5         while(i<A.length&&j<B.length){
     6                 if(A.data[i]<=B.data[j])
     7                       C.data[k++]=A.data[i];
     8                 else
     9                       C.data[k++]=B.data[j];
    10         }
    11         while(i<A.length)
    12               C.data[k++]=A.data[i++];
    13         while(j<B.length)
    14               C.data[k++]=B.data[j++];
    15         C.length=k;
    16         return true;
    17 }
    View Code

             6、线性表(a1,a2,a3,...,an)中元素递增有序且按顺序存储在计算机内。要求设计一算法完成用最少时间在表中查找数值为x的元素,若找到将其与后继元素位置交换,若找不到将其插入表中并使表中元素仍递增有序。

             算法思想:顺序存储的线性表递增有序,可以顺序查找,也可以折半查找。题目要求用最少时间,应用折半查找法。

     1 void Search(ElemType A[],ElemType x){
     2         int low=0,high=n-1;
     3         while(low<high){
     4                 mid=(low+high)/2;
     5                 if(A[mid]==x)break;
     6                 else if (A[mid]<x)low=mid+1;
     7                 else high=mid-1;
     8      }
     9      if(A[mid]==x&&mid!=n-1){
    10           t=A[mid];A[mid]=A[mid+1];A[mid+1]=t;
    11      }
    12     if(low>high){
    13             for(i=n-1;i>high;i--)A[i+1]=A[i];
    14             A[i+1]=x;
    15     }
    16 }
    View Code

           7、设将n(n>1)个整数存放到一堆数组R中。试设计一个在时间和空间两方面都尽可能高校的算法。将R中保存的序列循环左移p(0<p<n)个位置,即将R中的数据由(X0,X1,...,Xn-1)变换为(Xp,Xp+1,...,Xn-1,X0,X1,...,Xp-1)。

               算法思想:可以将这个问题看作是吧数组ab转换成ba(a代表数组的前p个元素,b代表数组中余下的n-p个元素),先将a逆置得到a-1b,再将b逆置得到a-1b-1,最后将整个逆置得到

    (a-1b-1-1=ba。设Reverse函数执行将数组元素逆置的操作。两个参数分别表示数组中待转换元素的始末位置。实现如下:

     1 void Reverse(int R[ ], int from, int to){
     2        int i,temp;
     3        for(i=0;i<(to-from+1)/2;i++){
     4             temp=R[from+i];R[from+i]=R[to-i];R[to-i]=temp;
     5        }
     6 }
     7 
     8 void main(int R[ ], int n,int p){
     9         Reverse(R,0,p);
    10         Reverse(R,p,n-1);
    11         Reverse(0,n-1);
    12 }
    View Code

             上述算法中,三个Reverse函数的时间复杂度分别为O(p/2),O((n-p)/2),O(n/2),故所设计的算法时间复杂度为O(n),空间复杂度为O(1)。

         8、一个长度为L的升序序列S,处在第[L/2]个位置的数称为S的中位数。例如,若序列S1=(11,13,15,17,19),则S1 的中位数是15,两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若S2=(2,4,6,8,20),则S1和S2的中位数是11.现在有两个等长的升序序列A和B,设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列A和B的中位数。

             算法思想:一开始我用了快速排序将两个序列进行合并排序(与第5题类似)。后来看了答案,才知道另一种更高效的算法。

                          分别求两个升序序列A、B的中位数,设为a和b,求序列A、B的中位数过程如下: 

                          1. 若a=b,则a或b即为所求中位数,算法结束

                          2. 若a<b,则舍弃序列A中较小的一半,同时舍弃序列B中较大的一半,要求两次舍弃的长度相等。

                          2. 若a>b,则舍弃序列A中较大的一半,同时舍弃序列B中较小的一半,要求两次舍弃的长度相等。

                         在保留的两个升序序列中,重复过程1,2,3,直到两个序列中均只含一个元素时为止,较小者即为所求的中位数。

           实现如下: 算法的时间复杂度为O(log2n),空间复杂度为O(1).

     1 int M_Search(int A[ ],int B[ ],int n){
     2     int s1=0,d1=n-1,m1,s2=0,d2=n-1,m2;
     3     while(s1!=d1&&s2!=d2){
     4          m1=(s1+d1)/2;
     5          m2=(s2+d2)/2;
     6          if(A[m1]=B[m2])
     7             return A[m1]
     8          if(A[m1]<B[m2]){
     9               if ((s1+d1)/2==0){
    10                     s1=m1;
    11                     d2=m2;
    12                }
    13               else{
    14                     s1=m1+1;
    15                     d2=m2;
    16               }
    17          }
    18        else{
    19             if((s1+d1)/2==0){
    20                          d1=m1; 
    21                          s2=m2;
    22            }
    23            else{
    24                          d1=m1;
    25                          s2=m2+1; 
    26             }
    27        }
    28    }
    29   return A[s1]<B[s2]?A[s1]:B[s2];
    30 }
    View Code

     

  • 相关阅读:
    Zabbix学习记录
    json_encode 函数使用中报错提示缺少两个参数
    MAC 上搭建一个本地LNMP环境学习laravel(一)
    mysql root 密码重置
    phpstorm格式化代码导致模板报错
    Get 和 Post
    axios设置请求超时时间 timeout
    charles安装配置 for Mac
    让 div 的高度等于宽度,的小技巧
    Git命令行删除本地和远程分支
  • 原文地址:https://www.cnblogs.com/tracylining/p/3394038.html
Copyright © 2011-2022 走看看