线性表的应用——线性表的合并

线性表的合并

初始条件:线性表la和lb
算法:
依次从lb中取出元素,查看是否存在la中,不存在则插入
顺序线性表的实现:

//线性表的合并
void unionList(SqList* &la,SqList* &lb){
    //从一个表中获取元素,再和另一个表中的数据进行比较
    int lena,lenb;
    lena=GetLength(la);
    lenb=GetLength(lb);
    for(int i=1;i<=lena;i++){
        ElemType e;
        GetElem(la,i,e);
        if(!LocateElem(lb,e)){
            ListInsert(lb,++lenb,e);
        }
    }
}

单链表表示的顺序表合并:

//线性表的合并,排除相同元素
void unionLink(LinkList &la,LinkList &lb){
    Lnode *pa,*pb;
    pa=la;
    pb=lb;
    int lena;
    getLinkLength(la,lena);
    int lenb;
    getLinkLength(lb,lenb);
    ElemType r;
    //从一个里面拿出数据,看一下另一个里面是否含有该数据
    for(int i=1;i<=lenb;i++){
        getElemI(lb,i,r);//得到数据r
        if(!LocteElemE(la,r)){
            insertLink(la,++lena,r);
        }
    }
}

算法的时间复杂度都是一样的:O(length(la)*length(lb))
完整代码:

#include <iostream>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define MAXSIZE 100
using namespace std;
typedef int Status;//返回值类型
typedef char ElemType;//状态
typedef struct
{
    ElemType elem[MAXSIZE];//对应方式二初始化
    //ElemType* elem;对应方式一初始化
    int length;
}SqList;
Status InitList2(SqList* &L){//改变形参中的内容并且使用它则需要用引用,解析:https://blog.csdn.net/eye123456789/article/details/79794461
    //L.elem = (ElemType *)malloc(MAXSIZE * sizeof(ElemType));
    L=(SqList*)malloc(sizeof(SqList));//(SqList *)表示把这个指针转型为SqlList结构的指针
    //L=new SqList;也可以实现
    if(!L->elem){exit(OVERFLOW);}
    L->length=0;
    return OK;
}
Status InitList(SqList &L){
    //L.elem = (ElemType *)malloc(MAXSIZE * sizeof(ElemType));
    //L.elem=new ElemType[MAXSIZE];
    //开辟一个存储空间,并把这块存储空间的基地址赋值给elem
    if(!L.elem){exit(OVERFLOW);}
    L.length=0;
    return OK;
}
void DestoryList(SqList* &L){
    //注意malloc用free,new用delete
    if(L) free(L);
        //delete L;

}
void ClearList(SqList* &L){
    L->length=0;
}
int GetLength(SqList* L){
    return L->length;
}
int IsEmpty(SqList* L){
    if(L->length==0) return 1;
    else return 0;
}
//取线性表中i号元素
int GetElem(SqList* L,int i,ElemType &e){
    if(i<1||i>L->length) return ERROR;
    e=L->elem[i-1];
    return OK;
}
//查找算法
int LocateElem(SqList* L,ElemType &e){
    for(int i=0;i<L->length;i++){
        if(L->elem[i]==e){
            return ++i;
        }
    }
    return 0;

}
Status AddElem(SqList* &L,ElemType e){
    if(L->length==MAXSIZE) return ERROR;
    L->elem[L->length++]=e;
    return OK;
}

Status ListInsert(SqList* &L,int i,ElemType e){
    if(i<1||i>(L->length+1)){
        return ERROR;
    }
    if(L->length==MAXSIZE) return ERROR;
    for(int j=L->length-1;j>=i-1;j--){
        L->elem[j+1]=L->elem[j];
    }
    L->elem[i-1]=e;
    L->length++;
    return OK;
}

void selectList(SqList* L){
    for(int i=0;i<L->length;i++){
        printf("%c ",L->elem[i]);
    }
}

Status ListDelete(SqList* &L,int i,ElemType &e){
    if(i<1||i>L->length) return ERROR;
    e=L->elem[i-1];
    for(int j=i-1;j<L->length;j++){
        L->elem[j]=L->elem[j+1];
    }
    L->length--;
    return OK;
}
//线性表的合并
void unionList(SqList* &la,SqList* &lb){
    //从一个表中获取元素,再和另一个表中的数据进行比较
    int lena,lenb;
    lena=GetLength(la);
    lenb=GetLength(lb);
    for(int i=1;i<=lena;i++){
        ElemType e;
        GetElem(la,i,e);
        if(!LocateElem(lb,e)){
            ListInsert(lb,++lenb,e);
        }
    }
}

//有序表的合并——顺序实现
SqList* mergeList(SqList* &la,SqList* &lb){
    SqList* lc;
    InitList2(lc);
    int lena,lenb,pa_last=0,pb_last=0;
    lena=la->length;
    lenb=lb->length;
    while(pa_last<lena&&pb_last<lenb){
        if(la->elem[pa_last]<lb->elem[pb_last]){
            lc->elem[lc->length++]=la->elem[pa_last++];
        }else{
            lc->elem[lc->length++]=lb->elem[pb_last++];
        }
    }
    while(pa_last<lena){
        lc->elem[lc->length++]=la->elem[pa_last++];
    }
    while(pb_last<lenb){
        lc->elem[lc->length++]=lb->elem[pb_last++];
    }
    return lc;
}


int main()
{
    SqList* L;
    InitList2(L);
    //printf("长度为:%d",L->length);
    ElemType e='a';
    AddElem(L,e);
    AddElem(L,'c');
    AddElem(L,'d');
    AddElem(L,'f');
    selectList(L);
    printf("\n===============\n");

    SqList* Lb;
    InitList2(Lb);
    //printf("长度为:%d",L->length);
    AddElem(Lb,e);
    AddElem(Lb,'e');
    AddElem(Lb,'f');
    AddElem(Lb,'g');
    selectList(Lb);
    printf("\n===============\n");
    //unionList(L,Lb);
    SqList* lc=mergeList(L,Lb);
    selectList(lc);
    printf("\n===============\n");
    //selectList(L);
    //printf("\n");
    //ListInsert(L,2,'b');
    //ElemType r;
   // ListDelete(L,4,r);
   // selectList(L);
   // printf("\n被删除元素为:%c",r);
    //ElemType r;
    //GetElem(L,1,r);
    //printf("a:%c\n",r);
    //printf("%d",LocateElem(L,e));
    //printf("%d",IsEmpty(L));

    return 0;
}

链表实现的完整代码:

#include <iostream>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define MAXSIZE 100
using namespace std;
typedef int Status;//返回值类型
typedef char ElemType;//数据类型
using namespace std;
typedef struct Lnode{
    ElemType data;
    Lnode* next;
}Lnode,*LinkList;
//带头结点链表初始化
//1.将链表指向头结点,并且头结点的下一个指向为空
Status initList(LinkList &L){
    //Lnode L=new Lnode;//c++语法用delete销毁,c的语法为;用free销毁
    L=(LinkList)malloc(sizeof(Lnode));
    L->next=nullptr;
    return OK;
}
//判断链表是否为空
int isEmpty(LinkList L){
    if(L->next!=nullptr) return 0;
    else return 1;
}
//销毁单链表
void destoryLink(LinkList &L){
    LinkList p;
    //注意点:L->next=null时是最后一个节点,不是循环结束的条件
    //循环结束的条件为L=null;
    //while(L!=nullptr){
     //   p=L;
     //   L=L->next;
     //   free(p);
    //}
    //或者
    p=L;
    //这里的循环结束的条件为L=null或者p=null
    while(p){
        L=L->next;
        free(p);
        p=L;
    }
}
//清空链表(头结点保存,从首元结点开始删除)
Status clearLink(LinkList &L){

    LinkList pre,cur;
   // if(L->next!=nullptr){
    //    pre=L->next;
    //    cur=pre->next;
    //    while(cur){
     //       free(pre);
     //       pre=cur;
     //       cur=cur->next;
      //  }
      //}
    pre=L->next;
    while(pre){
        cur=pre->next;
        free(pre);
        pre=cur;
    }
    L->next=nullptr;//头结点的指针域设置为空
    return OK;
}
//求单链表的表长
void getLinkLength(LinkList L,int &len){
    LinkList p;
    p=L->next;
    len=0;//设置初值
    while(p!=nullptr){
        len++;
        p=p->next;
    }
}
//取第i个元素值
Status getElemI(LinkList &L,int i,ElemType &e){
    int index=1;
    Lnode* p;
    p=L->next;//首元结点,所以index从1开始
    //如果一开始j>i说明要找的位置i比1小,是非法的
    while(p&&index<i){
        p=p->next;
        index++;
    }
    if(!p||index>i) return ERROR;
    e=p->data;
    return ERROR;
}
//按值查找,返回地址
Lnode*  LocteElemE(LinkList L,ElemType e){
    Lnode* p;
    p=L->next;
    while(p&&p->data!=e){
        p=p->next;
    }
    return p;
}
//按值查找,返回在第几个
int LocateElemE2(LinkList L,ElemType e){
    int i=1;
    Lnode* p;
    p=L->next;
    while(p&&p->data!=e){
        p=p->next;
        i++;
    }
    if(p==nullptr) return 0;
    else return i;
}
Status insertLink(LinkList &L,int i,ElemType e){
   Lnode* p=L;
   int index=0;
   while(p&&index<(i-1)){
        p=p->next;
        index++;
   }
   if(!p||index>i-1){//!p说明大于表长+1;index>i-1说明小于1
        return ERROR;
   }else{
       Lnode* s=(LinkList)malloc(sizeof(Lnode));
       s->data=e;
       s->next=p->next;
       p->next=s;
       return OK;
   }
}

Status deleteLink(LinkList &L,int i,ElemType &e){
    int index=0;
    Lnode* p;
    p=L;
    //或者需要用中间变量存储p->next
    //Lnode* q;
    while(p&&index<(i-1)){//index=i-1或者p为空的时候跳出循环
        p=p->next;
        index++;
    }
    if(p||index>(i-1)){
        return ERROR;
    }else{
        //q=p->next;
        //p->next=q->next;
        //e=q->data;
        e=p->next->data;
        p->next=p->next->next;
        return OK;
    }

}
//头插法
void headInsert(LinkList &L,ElemType e){
    Lnode* p=(LinkList)malloc(sizeof(Lnode));
    //或者用户输入这个元素的值
    //cin>>e;
    //scanf(e);
    p->data=e;
    p->next=L->next;//原来的接在新节点的后面
    L->next=p;//新节点接在头结点的后面
}
//尾插法
void tailInsert(LinkList &L,int n){

    Lnode* tail;
    tail=L;//指向头结点
    while(n!=0){
        Lnode* p=new Lnode;//记得每次都要开辟一块空间,否则输入会产生错误
        cin>>p->data;
        p->next=nullptr;//新指针的下一个指针域设置为空
        tail->next=p;//把尾指针的下一个指向当前的新指针
        tail=p;//移动尾指针的位置
        n--;//减少
    }
}

//遍历链表
void selectLink(LinkList L){
    Lnode* p;
    p=L->next;
    if(p==nullptr){
        printf("这个链表是空的!");
    }
    while(p!=nullptr){
        printf("p->data: %c\n",p->data);
        p=p->next;
    }
}
//线性表的合并,排除相同元素
void unionLink(LinkList &la,LinkList &lb){
    Lnode *pa,*pb;
    pa=la;
    pb=lb;
    int lena;
    getLinkLength(la,lena);
    int lenb;
    getLinkLength(lb,lenb);
    ElemType r;
    //从一个里面拿出数据,看一下另一个里面是否含有该数据
    for(int i=1;i<=lenb;i++){
        getElemI(lb,i,r);//得到数据r
        if(!LocteElemE(la,r)){
            insertLink(la,++lena,r);
        }
    }
}
//有序表的合并
void mergeLink(LinkList &la,LinkList &lb){
    Lnode* lc,*pa,*pb,*pc;
    lc=la;
    pc=lc;
    pa=la->next;
    pb=lb->next;
    while(pa!=nullptr&&pb!=nullptr){
        if(pa->data>=pb->data){
            pc->next=pb;
            pb=pb->next;
            pc=pc->next;
        }else{
            pc->next=pa;
            pa=pa->next;
            pc=pc->next;
        }
    }
    pc->next=pa?pa:pb;//三目运算符
    delete lb;
}

int main()
{
    //LinkList L;
    //initList(L);
    //ElemType elem[5]={'a','b','c','d','e'};
    //for(int i=4;i>=0;i--){
    //    headInsert(L,elem[i]);
    //}
    //tailInsert(L,5);
    //selectLink(L);
    //insertLink(L,6,'f');
    //printf("插入后:\n");
    //ElemType result;
   // getElemI(L,5,result);
    //printf("取出第5个元素的值为%c\n",result);
    //Lnode* p=LocteElemE(L,'a');
    //printf("按值查找返回地址:%c\n",p->data);
    //int i=LocateElemE2(L,'a');
   // printf("按值查找返回第几个: %d\n",i);
   // selectLink(L);
    //int len;
    //getLinkLength(L,len);
    //printf("链表长度:%d\n",len);
    //==========================下面测试线性表的合并
    LinkList la,lb;
    initList(la);
    initList(lb);
    tailInsert(la,5);
    selectLink(la);
    tailInsert(lb,5);
    selectLink(lb);
    //unionLink(la,lb);
    //printf("======合并后数据=======\n");
    //selectLink(la);
    mergeLink(la,lb);
    printf("========有序表的合并======\n");
    selectLink(la);
    return 0;
}
  • 1
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜菜iwi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值