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 原理同上

                                                                                         

  • 相关阅读:
    Windows Store App 主题动画
    Windows Store App 过渡动画
    Windows Store App 控件动画
    Windows Store App 近期访问列表
    Windows Store App 文件选取器
    Windows Store App 访问应用内部文件
    Windows Store App 用户库文件分组
    Windows Store App 获取文件及文件夹列表
    Windows Store App 用户库文件夹操作
    Windows Store App 用户库文件操作
  • 原文地址:https://www.cnblogs.com/webcyh/p/11325750.html
Copyright © 2011-2022 走看看