单链表(二)

13.

//La和Lb按值非递减,归并La和Lb,得到新的单链表Lc。
//使得Lc也按值非递减且不含重复元素,并占用原来的空间。
/*
用两个指针分别指向La和Lb的第一个数据结点。每次取较小的结点“尾插”到Lc中。
如果带插入结点与尾结点相同,则释放该结点,反之则追加到尾部。
重复上述步骤,直到其中一个链的结点被搜索完。随后再将剩余结点直接追加到Lc尾部
*/
void insertNode(LinkNode *&pTail,LinkNode *node){//在Lc尾部插入新结点
    if(pTail->data==node->data){//如果已经存在(重复结点则直接释放)
        free(node);
    }
    else{//否则进行尾插,更新pTail指针
        node->next=NULL;
        pTail->next=node;
        pTail=node;
    }
}
void mergeLinkList(LinkList &La,LinkList &Lb,LinkList &Lc){
    LinkNode *pA=La->next;
    LinkNode *pB=Lb->next;
    free(Lb);//释放Lb头结点
    Lc=La;//Lc抢占La头结点
    Lc->next=NULL;
    LinkNode *pTail=Lc;//Lc的尾指针

    while(pA!=NULL && pB!=NULL){
        if(pA->data<pB->data){
            LinkNode *temp=pA;
            pA=pA->next;
            insertNode(pTail,temp);
        }
        else{
            LinkNode *temp=pB;
            pB=pB->next;
            insertNode(pTail,temp);
        }
    }
    while(pA!=NULL){
        LinkNode *temp=pA;
        pA=pA->next;
        insertNode(pTail,temp);
    }
    while(pB!=NULL){
        LinkNode *temp=pB;
        pB=pB->next;
        insertNode(pTail,temp);
    }
}

14.

//带头单链表中所有元素的数据值按递增顺序排列,删除链表中大于min且小于max的元素
void deleteNode(LinkList &L,int min,int max){
    LinkNode *pre=L;
    LinkNode *p=L->next;
    while(p!=NULL && p->data<=min){//找到第一个大于min的结点
        pre=p;
        p=p->next;
    }
    while(p!=NULL && p->data<max){//删除所有大于min小于max的结点
        pre->next=p->next;
        free(p);
        p=pre->next;
    }
}

15.

//对链表使用冒泡排序
void sort(LinkList &L){
    int length=0;
    LinkNode *p=L->next;
    while(p!=NULL){
        length++;
        p=p->next;
    }

    for(int i=0;i<length-1;i++){
        p=L->next;
        for(int j=0;j<length-1-i;j++){
            if(p->data>p->next->data){
                int temp=p->data;
                p->data=p->next->data;
                p->next->data=temp;
            }
            p=p->next;
        }
    }
}

16.

//设L为单链表头结点地址,其数据结点都是正整数可能存在相同数值的结点。
//设计一个时间复杂度最低的算法
//利用直接插入排序把该链表整理成有序递增的链表并将重复结点删除
void insertSort(LinkList &L){
    LinkNode *pData=L->next;
    L->next=NULL;

    while(pData!=NULL){
        LinkNode *pre=L;
        LinkNode *p=L->next;
        while(p!=NULL&&pData->data>p->data){
            pre=p;
            p=p->next;
        }
        LinkNode *temp=pData;
        pData=pData->next;
        if(p!=NULL && p->data==temp->data){//p!=NULL不能忘
            free(temp);
        }
        else{
            temp->next=pre->next;
            pre->next=temp;
        }
    }
}

17.

18.

//设计一个算法,判断Lb是否为La的子链,子链的定义为:Lb中的从前到后的所有结点
//的数据域都按照原有的顺序出现在La中
int isSub(LinkList La,LinkList Lb){//判断Lb是否为La的子链
    LinkNode *start=La->next;//匹配不成功时start后移一个结点
    LinkNode *pA=start;

    LinkNode *pB=Lb->next;//匹配不成功时pB回到Lb第一个结点

    while(pA!=NULL && pB!=NULL){
        if(pA->data==pB->data){
            pA=pA->next;
            pB=pB->next;
        }
        else{
            start=start->next;
            pA=start;
            pB=Lb->next;
        }
    }
    if(pB==NULL) return 1;
    return 0;
}

19.

//两个单词有相同的后缀时,可共享相同后缀的存储空间。例如:"act"和"dict"
//设La和Lb分别指向两个单词所在单链表的头结点。
//设计算法查找公共后缀的起始位置
/*
将La的长度记为a,Lb的长度记为b。假设Lb为较长的链,那么b>a。先访问Lb中的b-a个结点,
然后同时访问La和Lb中的结点,直到找到公共结点
*/
int getLength(LinkList L){
    int length=0;
    LinkNode *p=L->next;
    while(p!=NULL){
        length++;
        p=p->next;
    }
    return length;
}
LinkNode *getCommonNode(LinkList La,LinkList Lb){
    int lengthLa=getLength(La);
    int lengthLb=getLength(Lb);
    LinkNode *pA=La->next;
    LinkNode *pB=Lb->next;
    if(lengthLa>lengthLb){
        int i=1;
        while(i<=lengthLa-lengthLb){
            pA=pA->next;
            i++;
        }
    }
    if(lengthLb>lengthLa){
        int i=1;
        while(i<=lengthLb-lengthLa){
            pB=pB->next;
            i++;
        }
    }
    while(pA->data!=pB->data){
        pA=pA->next;
        pB=pB->next;
    }

    return pA;
}

20.

//长度为n的单链表L(L1,L2,...,Ln),编写时间复杂度、空间复杂度最低的算法
//将单链表转化成L'(L1,Ln,L2,Ln-1,L3,Ln-2...)(仍是n个元素)
/*
算法思想:将L分割为front和rear两段,逆置rear。
依次取front和rear中的一个结点,插入到表尾。
重复上述步骤,直至一个链表为空。然后将剩余结点插入尾部即可
*/
void change(LinkList L,int n){
    LinkNode *p=L->next;
    int j=1;
    while(j<n/2){//找到第n/2个结点
        p=p->next;
        j++;
    }

    LinkNode *pFront=L->next;//pFront指向前半段(无头结点)
    L->next=p->next;//L指向后半段(有头结点,方便逆置)
    p->next=NULL;
    //将后半部分逆置
    p=L->next;
    L->next=NULL;
    while(p!=NULL){
        LinkNode *temp=p;
        p=p->next;
        temp->next=L->next;
        L->next=temp;
    }

    LinkNode *pRear=L->next;//pRear指向逆置完成的后半部分的第一个结点
    L->next=NULL;
    LinkNode *pTail=L;

    while(pFront!=NULL && pRear!=NULL){
        LinkNode *temp=pFront;
        pFront=pFront->next;
        temp->next=pTail->next;
        pTail->next=temp;
        pTail=temp;

        temp=pRear;
        pRear=pRear->next;
        temp->next=pTail->next;
        pTail->next=temp;
        pTail=temp;
    }
    if(pRear!=NULL){
        pTail->next=pRear;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值