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

    线性表的逻辑特征:至少含一个元素,则只有唯一的开始元素和终端元素,除了开始元素外其他元素有且仅有一个前驱结点

    不同实际问题当中,数据元素的类型不同,但同一个线性表当中所有元素具有相同的类型,数据项一样,数据项类型一样

    线性表基本运算:

    初始化InitList(L) 作用创建一个空表

    销毁线性表DestroyLIst(L)释放L内存

    求线性表长度

    求线性表中第i个元素GetElem(L,i,e)

    按值查找位置(L,e)

    插入元素:在某个位置插入数据InsElem(L,x,i)

    删除元素在某个未知删除元素DelElem(L,e)

    输出元素DispList(L)   

    线性表的存储结构主要分为:顺序存储和链式存储 前者简称为顺序表

    线性表相当于一个特殊的数组这个‘数组’拥有一个记录其长度的元素:length 

    由于顺序表采用数组存放元素,而数组具有随机存取特性,所以顺序表局有随机存取特性

     
     
    
    #include<iostream>
    using namespace std;
    //定义线性表中数组的长度
    #define MaxSize 100
    //定义数组类型
    typedef int ElemType;
    //定义自定义类型结构体
    typedef struct{
    ElemType data[MaxSize];
    int length;
    } List;
    
    //初始化线性表
    void InitList(List &L){
       L.length=0;
    }
    
    
    //销毁线性表
    void DestroryList(List L){}
    
    
    
    //获取长度
    int GetLength(List &L){
     return L.length;
    }
    
    
    
    //在某个位置插入元素 函数返回类型为int为了判断是否插入成功
    int InsElem(List &L,ElemType a,int r){
     if(r<1||r>L.length+1){
        return 0;
     }
    int len=GetLength(L);
     //将r-1到L.length-1的的元素均往后挪一个位置
     for(int i=len;i>r-1;i--){//这里可能相对来说难理解 因为要在逻辑位置r处插入元素 应该将r-1和r-1之后的元素往后挪  L.data[r]=L.data[r-1]
       L.data[i]=L.data[i-1];
     } L.data[r-1]=a;
    //插入元素后长度加一
     L.length++;
    return 1;
    }
    
    
    
    
    //删除某个位置的元素
    int DelElem(List &L,int r){
      //判断位置是否正确
      if(r<1||r>L.length){
        return 0;
      }
      //将r-1到L.length-1的元素前移一位 最后执行L.data[L.length-2]=L.data[L.length-1]
      for(int i=r;i<L.length;i++){
        L.data[i-1]=L.data[i];
      }
      L.length--;
      return 1;
    }
    
    //返回某个元素的位置
    
    int LocaElem(List &L,ElemType a){
      int i=0;
    //这里可以使用while循环或者for循环
      while(L.data[i]!=a&&i<L.length){
        i++;
      }
      //如果循环完了还没找到元素返回0否则返回逻辑序号
      if(i>=L.length){
        return 0;
      }else{
        return i+1;
       }
    }
    
    
    //输出元素
    void DisList(List &L){
      if(L.length==0){
        cout<<"当前元素为空";
      }else{
        cout<<"线性表的元素如下:"<<endl;
        for(int i=0;i<L.length;i++){
         cout<<L.data[i]<<" ";
        }
       cout<<endl;
      }
    }
    
    
    
    
    
    //返回某个位置的元素的值
    int GetElem(List &L,ElemType a,int r){
      if(r>L.length||r<1){
         return 0;
      }else{
        a=L.data[r];
        return 1;
      }
    }
    
    int main(){
    /*
    实现功能用一个线性表
    :初始化InitList
    :销毁线性表 DestroryList
    :在某个位置插入元素 InsElem
    :删除元素DelElem
    :返回某个元素的位置LocaElem
    :显示元素DisList
    :返回长度
    :返回地某个位置的元素
    */
    //声明线性表
    List L;
    ElemType a;
    //初始化线性表
    InitList(L);
    //插入元素
    cout<<"插入元素1,3,5,12"<<endl;
    InsElem(L,1,1);
    InsElem(L,3,2);
    InsElem(L,5,3);
    InsElem(L,12,4);
    DisList(L);
    cout<<"返回第3个位置的元素"<<endl;
    GetElem(L,a,2);
    cout<<a<<endl;
    cout<<"长度"<<GetLength(L)<<endl;
    cout<<"获取元素3的位置"<<endl;
    cout<<LocaElem(L,3)<<endl;
    cout<<"删除第2个元素"<<endl;
    if(DelElem(L,2)){
    cout<<"删除成功"<<endl;
    }else{
    cout<<"删除失败"<<endl;
    }
    cout<<"输出所有元素"<<endl;
    DisList(L);
    cout<<"销毁<<endl";
    DestroryList(L);
    
    return 0;
    }
    
    
     

    结果如下:

     将上面的顺序表的基本运算分装成一个头文件 48.h

    下面使用 注意主函数只能有一个

    从r开始删除n个元素

    #include "48.h"
    //从第r个元素开始删除n个元素
    int delElems(List &L,int r,int n){
      //判断参数是否正确
      if(r<1||n<1||r+n-1>L.length){
        return 0;
      }
      //从r+n-1开始向前移动n个位置 注意一个问题   从r开始删除n个元素 实际上逻辑序列删除 r 到 r+n-1 也就是实际顺序 r-1 到r+n-2   r+n-1不删除
      for(int j=r+n-1;j<L.length;j++){
         L.data[j-n]=L.data[j];
      }
      L.length-=n;
      return 1;
    }
    int main(){
    List L;
    InitList(L);
    InsElem(L,1,1);
    InsElem(L,3,2);
    InsElem(L,11,3);
    InsElem(L,12,4);
    InsElem(L,11,5);
    InsElem(L,21,6);
    InsElem(L,31,7);
    InsElem(L,13,8);
    InsElem(L,155,9);
    InsElem(L,11,10);
    InsElem(L,1,7);
    InsElem(L,10,4);
    DisList(L);
    delElems(L,2,5);
    DisList(L);
    
    return 0;
    }

    //将所有奇数放到偶数前面
    void move(List &L){
      int i=0;
      int j=L.length;
      //一个从前面找偶数 从后面找奇数 当中指导位置重合或者相交
      while(i<=j){
       while(L.data[i]%2==1) i++;
       while(L.data[j]%2==0) j--;
       if(i<j){
         ElemType a=L.data[i];
         L.data[i]=L.data[j];
         L.data[j]=a;
       }
      }
    }

    解析:

    一个从线性表开头开始找偶数 一个从尾巴 开始向前找奇数 当找到时判断此时i 和 j 的位置条件如果满足就交换顺序 一般只有两种情况:

    前面的奇数多或者前面的偶数多(将少部分的奇数放到偶数前面)

           

    二路归并

    3.在合并两个有序数组。如图2

          (1) 合并时,有两个指针分别指向有序数组A和B的起始元素,比较指针所指元素的大小,如果A[i]较小,则将A[i]

    存入数组C中,并且将i后移。循环比较i和j所指的元素。

          (2)当一个数组A的元素全部排之后,数组B中的指针就并没有指向B的末尾位置,将B中剩余元素全部存入到C中。

    //合并两个顺序表到一个线性表当中从小排到大的有序顺序表
    void merge(List &L1,List &L2,List &rst){
    int i=0;//L1下标
    int j=0;//L2下标
    int k=0;//rst的下标
    while(i<L1.length&&j<L2.length){
    if(L1.data[i]>L2.data[j]){
      rst.data[k]=L2.data[j];
      k++;
      j++;
    }else if(L1.data[i]<L2.data[j]){
      rst.data[k]=L1.data[i];
      k++;
      i++;
    }else{
      rst.data[k]=L1.data[i];
      k++;
      i++;
      rst.data[k]=L2.data[j];
      k++;
      j++;
    }
    }
    //到这一步将剩下的直接放在上面
    while(i<L1.length){
      rst.data[k]=L1.data[i];
      k++;
      i++;
    }
    
    while(j<L2.length){
      rst.data[k]=L2.data[j];
      k++;
      j++;
    }
    
    
    rst.length=k;
    }

    还有一个相似的例子:已知有两个递增有序表A和B 设计算法将A和B的所有公共元素产生一个顺序表C 原理同上

                                                                                         

  • 相关阅读:
    Demo:刮刮卡橡皮擦效果
    养成良好的代码编写习惯
    我的百科
    专业英语词汇
    加载资源的类
    循环滚动翻页+居中项缩放
    学习笔记—Node中模块化规范
    学习笔记—Node中的EventLoop
    学习笔记—Node的全局对象
    学习笔记—Node的基本概念
  • 原文地址:https://www.cnblogs.com/webcyh/p/11325750.html
Copyright © 2011-2022 走看看