zoukankan      html  css  js  c++  java
  • 数据结构_线性表之顺序表(2)

    此处记录常见的顺序表题目。

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

    下面给出了C++与C的解法。

    算法思想:1.定义i,j变量,i变量用来指示顺序表的下标,用于指示所有元素,j元素用来保存目的顺序表长度,并用来指示下一个可以存储合法数据的位置。

    2.遍历顺序表所有元素,当数据不是x时,则把合法数据加入线性表,j变量加1。

    3.当遍历到的数据为x时,则不去理会,继续执行下次操作。

    总结:简单说,就是合法数据加入顺序表,顺序表长度加一。

    例子:

    /*对长度为n的顺序表L,编写一个时间复杂度为O(n),空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素*/
    #define MAXSIZE 50
    typedef int ElemType;
    typedef struct{
        ElemType data[MAXSIZE];
        int length;
    }SqList;
    //1.C语言
    bool Del_x_1(SqList *L,ElemType x){//这里给进结构体的指针,因为要改变原结构体内顺序表的值,给进指针会更方便一些,速度上也会快一些。
        int i,j;
        if(L->length==0)
            return false;
        for(i=0,j=0;i<L->length;i++)
            if(L->data[i]!=x)
                L->data[j++]=L->data[i];//注意这里i不要++,因为i是由循环体控制的
        L->length=j;//length是计算的个数,从1开始算起,所以j++后,作为长度是正好的
        return true;
    }
    //2.C++语言
    bool Del_x_1(SqList &L,ElemType x){//这里给进结构体的指针,因为要改变原结构体内顺序表的值,给进指针会更方便一些,速度上也会快一些。
        int i,j;
        if(L.length==0)
            return false;
        for(i=0,j=0;i<L.length;i++)
            if(L.data[i]!=x)
                L.data[j++]=L.data[i];//注意这里i不要++,因为i是由循环体控制的
        L.length=k;//length是计算的个数,从1开始算起,所以j++后,作为长度是正好的
        return true;
    }

     2.从顺序表L中删除元素x到y之间的所有元素(x<=y)

    算法思想:1.定义i,j变量,i变量用来指示顺序表的下标,用于指示所有元素,用于遍历;j元素用来记录不合法的元素个数。i-j元素用来保存目的顺序表长度,并用i-j来指示下一个可以存储合法数据的位置。

    2.遍历顺序表所有元素,当数据是合法数据时,则把合法数据加入线性表。

    3.当遍历到的数据为非法数据时,则j自增1,继续执行下次操作。

    4.i-j总能够表示下一个合法数据可以存储的位置。

    总结:简单说,就是合法数据加入顺序表,顺序表长度加一。

    下面是王道数据结构给出的习题思路:

    //C语言解决
    void delallxy(Sqlist *l,int x,int y)
    {
        int i=0;
        int j=0;
        while(i<l->length)
        {
            if(l->data[i]>=x && l->data[i]<=y)
                j++;
            else
                l->data[i-j]=l->data[i];
            i++;
    
        }
        l->length-=j;
    }
    //C++解决
    void delallxy(Sqlist &l,int x,int y)
    {
        int i=0;
        int j=0;
        while(i<l.length)
        {
            if(l.data[i]>=x && l.data[i]<=y)
                j++;
            else
                l.data[i-j]=l.data[i];
            i++;
    
        }
        l.length-=j;
    }

    我觉得上面的思路虽然正确,但是看着很别扭,因为说白了,算法思路还是和第一题的思路一样,合法数据加入线性表,不合法则不予理会,所以我稍微修改了一下。

    //C语言解决
    void delallxy(Sqlist *l,int x,int y)
    {
        int i=0;
        int j=0;
        while(i<l->length)
        {  i++;//i总是自增1,用于遍历数据
            //如果是合法数据,则加入顺序表,j+1
            if(l->data[i]<x && l->data[i]>y)
           {
                data[j]=data[i]
                j++;
            }
        }
        l->length=j;
    }
    //C++解决
    void delallxy(Sqlist &l,int x,int y)
    {
        int i=0;
        int j=0;
        while(i<l.length)
        {
            i++;//i总是自增1,用于遍历数据
            //如果是合法数据,则加入顺序表,j+1
            if(l.data[i]<x && l.data[i]>y)
           {
                data[j]=data[i]
                j++;
            }
        }
        l.length=j;
    } 

    个人总结:

    (1)诸如此类删除某个匹配的数字,或者某个数字范围的顺序表,都是按照合法数据加入,非法数据不予理会这个通用思路就好。

    (2)虽然对于有些特殊点的题目,比如顺序表是有序的,那可能只要记录第一个大于X,和第一个大于Y,删除X到Y前连续的一块数字段就好。但是最后写出来的代码,都和我说的通用思路写的时间复杂度,空间复杂度差不多,那就记住最通用的就好了。

    3.删除有序顺序表的重复值,使其中每个元素都不相同。

    算法思路:因为是顺序有序表,所以需要删除重复的连续位置即可,每个元素每一次都与整段数字最后一个比较,若相同不予理会,若不同加入顺序表。

    //C语言解决
    void delete_some(Sqlist *l)
    {
        int i,j;//i用于指示可以存放的下一个合法数据的位置,j遍历数据
        for(i=0,j=1;j<L.length;j++)
            if(L->data[i]!=L->data[j])
               L->data[++i]=L->data[j]
        l->length=i+1;
    }
    //C++解决
    void delall_some(Sqlist &l)
    {
        int i,j;
        for(i=0,j=1;j<L.length;j++)
            if(L.data[i]!=L.data[j])
               L.data[++i]=L.data[j]
        l.length=i+1;
    } 

     4.合并两个顺序表,使其仍然为顺序表

    算法思路:分别把两个顺序表当前最小的值拿出来比较,如果谁小,谁就插入新数组,所以需要三个数组,时间复杂度T=max{f(m),f(n)},m,n为两个数组的长度

    //C语言
    bool Merge(SqList A, SqList B, SqList *C) {
        //将有序顺序表AB合并为有序的顺序表C
        int i, j, k = 0;
        while (i < A.length&&j < B.length) {
            if (A.data[i] <= B.length)
                C->data[k++] = A.data[i++];
            else
                C->data[k++] = B.data[j++];
        }
        //若A没完,则把剩下的A,都加入C
        while (i < A.length)
            C->data[k++] = A.data[i++];
        //若B没完,则把剩下的B,都加入C
        while (i < B.length)
            C->data[k++] = B.data[j++];
        C->length = k;
        return true;
    }
    //C++
    bool Merge(SqList A, SqList B, SqList &C) {
        //将有序顺序表AB合并为有序的顺序表C
        int i, j, k = 0;
        while (i < A.length&&j < B.length) {
            if (A.data[i] <= B.length)
                C.data[k++] = A.data[i++];
            else
                C.data[k++] = B.data[j++];
        }
        //若A没完,则把剩下的A,都加入C
        while (i < A.length)
            C.data[k++] = A.data[i++];
        //若B没完,则把剩下的B,都加入C
        while (i < B.length)
            C.data[k++] = B.data[j++];
        C.length = k;
        return true;
    }

     5.线性表元素(a1,a2,a3……an)为有序顺序表,要求设计一算法,完成最短时间在表中找到该元素,若找到,将其与后继元素互换,若找不到,则插入表中使其仍保持有序

    算法思想:

    (1)使用到了折半查找,即二分法,每次都拿中间的数字与所求的数字进行比较,若大于中间的数字,则舍去左边,进行比较右边,反之亦然。

    (2)需要注意的是,二分法无需考虑奇偶个,因为(low+hight)/2始终向下取整,举例子:(1+5)/2=3,(1+6)/2=3。

    (3)二分法终止条件为,low>hight;下面图为终止条件:

     

    void SearchExchangeInsert(ElemType A[],ElemType x){
      int low=0,high=n-1,mid;//low和high指向顺序表下界和上界的下标
      while(low<=high){
      mid=(low+high)/2;  //找中间位置
      if(A[mid]==x) break; //找到x,退出while循环
      else if (A[mid]<x) low=mid+1;  //到mid中点的右半部去查
      else high=mid-1;  //到中点mid的左半部去查
    }//下面两个if语句只会执行一个

    if (A[mid]==x&&mid!=n-1){//查找成功且x不是最后一个元素,若是最后一个元素则不予操作 ElemType t; t=A[mid]; A[mid]=A[mid+1]; A[mid+1]=t; } if (low>high){ //查找失败,X不在这个顺序表内,此时的high是最后一个小于x的数(在high后面插入)或者是high=-1(也是在high后面插入) for (i=n-1;i>high;i--) A[i+1]=A[i]; //后移元素 A[i+1]=x;//插入x } }

     6.顺序表逆置问题。

    奇数情况

     偶数情况

     处理代码一样:

  • 相关阅读:
    Python3之json模块
    How To Enable EPEL Repository in RHEL/CentOS 7/6/5?
    安装CentOS 6.x出现Disk sda contains BIOS RAID metadata
    详解hdparm: linux下的硬盘测速工具
    {转载}需要同时设置 noatime 和 nodiratime 吗?
    ubuntu17.10安装LAMP并测试部署php探针系统
    shell监控网卡状态,故障时自动重启网卡
    L2TP/IPSec一键安装脚本
    Linux系统下用find命令查找最近修改过的文件
    Hyper-V 手动导入虚机配置实例(转载)
  • 原文地址:https://www.cnblogs.com/hmy-666/p/13486460.html
Copyright © 2011-2022 走看看