链表(二)

7.设计一个带表头结点的单链表中所有的元素结点的数据值无序,编写一个函数删除介于给定两个
值之间的元素的元素

链表无序,逐个结点进行检查,执行删除

void RangeDelete(LinkList& L, int min, int max) {
    LNode* pr = L, * p = L->link;
    while (p != NULL) {
        if (p->data > min && p->data < max) {
            pr->link = p->link;
            free(p);
            p = pr->link;
        }
        else {
            pr = p;
            p = p->link;
        }
    }
}

8.给定两个单链表,编写算法找出两个链表的公共节点
两个链表有公共节点,即两个结点从某个节点开始,他们的next结点都指向同一个结点;由于单链
表的结点只能指向一个结点,所以后面都是重合的,不会出现分叉。拓扑形状为Y

应注意到这样一个事实:若两个链表有一个公共结点, 则该公共结点之后的所有结点都是重合的,
即它们的最后一个结点依然是重合的。因此, 我们判断两个链表是不是有重合的部分时, 只需要分
别遍历两个链表到最后一个结点。若两个尾结点是一样的, 则说明它们有公共结点, 否则两个链表
没有公共结点。然而, 在上面的思路中, 顺序遍历两个链表到尾结点时, 并不能保证在两个链表上
同时到达尾结点。这是因为两个链表长度不一定一样。但假设一个链表比另一个长k个结点, 我们先
在长1的链表上遍历k个结点, 之后再同步遍历, 此时我们就能保证同时到达最后一个结点。由于两
个链表从第一个公共结点开始到链表的尾结点, 这一部分是重合的, 因此它们肯定也是同时到达最后
一个公共结点的。于是在遍 第一个相同的结点就是第一个公共的结点。
根据这一思路中, 我们先要分别遍历两个链表得到它们的长度, 并求出两个长度之差。在长的链表
上先遍历长度之差个结点之后, 再同步遍历两个链表, 直到找到相同的结点, 或者, 直到链表结束

LinkList Search_lst_Common(LinkList L1, Linklist L2) {
    int len1 = Length(L1), len2 = Length(L2);
    LinkList longList, shortList;
    if (len1 > len2) {
        longList = L1->next; shortList = L2->next;
        dist = len1 - len2;
    }
    else {
        longList = L2->next; shortList = L1->next;
        dist = len2 - len1;
    }

    while (dist--)
        longList = longList->next;
    while (longList != NULL)
    {
        if (longList == shortList)
            return longList;
        else {
            longList = longList->next;
            shortList = shortList->next;
        }
    }
    return NULL;
}

9.给定一个带表头结点的单链表,设head为头指针,结点结构为(data,next),data为整形元素,
next为指针,试写出算法:按递增次序输出单链表中各个结点的数据元素,并释放结点所占的存储
结构

思想:链表遍历,每次遍历中找出整个链表的最小值元素,输出并释放结点所占空间;再查找次小值
元素,输出并释放空间,如此下去,直至链表为空。

void Min_Delete(LinkList& head) {
    LinkList* pre,* u;
    while (head->next != NULL) {
        pre = head;
        p = pre->next;
        while (p->next != NULL) {
            if (p->next->data < pre->next->data)
                pre = p;
            p = p->next;
        }
        print(pre->next->data);
        u = pre->next;
        pre->next = u->next;
        free(u);
    }
    free(head);
}

10.将一个带结点的单链表A分解为两个带头结点的单链表A和B,使得A表中含有原表中序号为奇数的
元素,而B表中含有原表中的序号为偶数的元素,且保持相对顺序不变

思想:遍历完整表,分别计算奇偶元素,分别尾插入到A和B表

LinkList DisCreat(LinkList& A) {
    linkList* B;
    Elem i = 0;
    B = (LinkList)malloc(sizeof(LNode));
    B->next = NULL;
    LNode* ra = A, * rb = B;

    p = A->next;
    A->next = NULL;
    while (p != NULL) {
        i++;
        if (i % 2 == 0) {
            rb->next = p;
            rb = p;
        }
        else {
            ra->next = p;
            ra = p;
        }
        p = p->next;
    }
    ra->next = NULL;
    rb->next = NULL;
    return B;
}

11.变形:将一个带结点的单链表A分解为两个带头结点的单链表A和B,使得A表中含有原表中序号为
奇数的元素,而B表中含有原表中的序号为偶数的元素,B表为逆序。

solution 1:
LinkList DisCreat(LinkList& A) {
    linkList* B;
    Elem i = 0;
    B = (LinkList)malloc(sizeof(LNode));
    
    LNode* ra = A, * rb = B,*q;
    B->next = NULL;
    p = A->next;
    A->next = NULL;
    while (p != NULL) {
        i++;
        if (i % 2 == 0) {
            rb->next = p;
            rb = p;
        }
        else {
            q = B->next;
            p->next = q;
            B->next = p;
        }
        p = p->next;
    }
    ra->next = NULL;
    return B;
}

solution 2:
LinkList DisCreat(LinkList & A) {
    LinkList B = (LinkList)malloc(sizeof(LNode));
    B->next = NULL;
    LNode* p = A->next, * q;
    LNode* ra = A;
    while (p != NULL) {
        ra->next = p; ra = p;
        p = p->next;

        //尾插法到B
        if (p != NULL) q = p->next;
        p->next = B->next;
        B->next = p;
        p = q;
    }
    ra->next = NULL;
    retuen B;
}

12.再一个递增的有序线性表中,有数值相同的元素。若存储方式为单链表,设计算法去掉数值相同
的元素,使表中不再有重复的元素

void Del_Same(LinkList& L) {
    LNode* p = L->next, * q;
    if (p == NULL) return;
    while (p->next != NULL) {
        q = p->next;
        if (p->data == q->data) {
            p->next = q->next;
            free(q);
        }
        else
            p = p->next;
    }
}

13.假设有两个按元素值递增次序排列的线性表,均以单链表形式存储。请编写算法将这两个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两.个单链表的结点存放归并后的单链表。

void MergeList(LinkList& La, LinkList& Lb) {
    LNode* r, * pa = La->next, * pb = Lb->next;
    La->next = NULL;    //作为结果存放的头指针

    while (pa && pb) {
        if (pa->data <= pb->data) {
            r = pa->next;
            pa->next = L->next;
            L->next = pa;
            pa = r;
        }
        else {
            r = pb->next;
            pb->next = L->next;
            L->next = pb;
            pb = r;
        }
        if (pa)
            pb = pa;
        while (pb) {
            r = pb->next;
            pb->next = L->next;
            L->next = pb;
            pb = r;
        }
        free(Lb);
    }
}

14.设A和B使两个单链表(带头结点),其中元素递增有序。设计一个算法从A和B中的公共元素产生
单链表C,要求不破坏A,B的结点(需要创建一个新的LNode链表)。

算法思想 : 表A、B都有序, 可从第一个元素起依次比较A、B两表的元素, 若元素值不等, 1值小的
指针往后移, 若元素值相等, 则创建一个值等于两结点的元素值的新结点, 使用尾插法插入到新的
链表中, 并将两个原表指针后移一位, 直到其中一个链表遍历到表尾。

void Get_Common(LinkList A, LinkList B) {
    LNode* p = A->next, * q = B->next, * r, * s;
    LinkList C = (LinkList)malloc(sizeof(LNode));
    r = C;
    while (p != NULL && q != NULL) {
        if (p->data < q->data)
            p = p->next;
        else(p->data > q->data)
            q = q->next;
        else {
            s = (LNode*)malloc(sizeof(LNode));
            s->data = p->data;
            r->next = s;
            r = s;
            p = p->next;
            q = q->next;
        }
    }
    r->next = NULL;
}

 

posted @ 2021-08-08 23:00  为红颜  阅读(158)  评论(0编辑  收藏  举报