广大考研数据结构复习之单链表

王道书籍上单链表的基本操作和课后部分习题

一:头文件的定义

#ifndef LINKLIST_H
#define LINKLIST_H
/**
 * @author Dawn
 * @date 2019年11月7日19:57:24
 * @version 1.0
 * 数据结构二轮复习之顺序表,不要问我为什么时间不对劲,电脑的机械硬盘坏了,晕,所有东西都没了,现在都在重写
 */

#include<stdio.h>
#include<stdlib.h>
#include<time.h>

typedef int ElemType;

typedef struct LNode {
    ElemType data;//数据域
    struct LNode* next;
}LNode, * LinkList;


//循环双链表,仅仅是为了17题写的,没有初始化,懒得写那些了,运行不出来的!!
typedef struct DSNode {
    ElemType data;
    struct DSNode* next;
    struct DSNode* prior;
}DSNode,*DSLinkList;

//==========================单链表的基本操作==============================
//1.头插法建立单链表(带头结点,没有特殊说明默认是带头节点的)
LinkList List_Insert_Head(LinkList& L);
LinkList List_Insert_NoHead(LinkList& L);//(不带头节点的)
//2.尾插法建立单链表
LinkList List_Insert_Tail(LinkList& L);
//3.按序号查找节点
LNode *GetElem(LinkList L, int i);
//4.按值查找节点
LNode* LocateElem(LinkList L, ElemType e);


//==========================课后习题======================================
//1.使用递归,删除不带头节点的单链表L中所有值为x的节点
void Del_X1(LinkList& L, ElemType e);
//2.在带头节点的单链表L中,删除L中所有值为x的节点
void Del_X2(LinkList& L, ElemType e);
//3.从尾到头输出带头结点的单链表L中的所有节点值;
void R_Print3(LinkList L);
//4.删除带头结点的单链表L中最小值的节点高效方法(该最小值节点唯一)
void Del_Min4(LinkList& L);
//5.带头结点的单链表逆置
void Reverse5(LinkList& L);
//6.使带头节点的单链表有序
void Sort_LinkList6(LinkList& L);
//7.删除无序带头节点的单链表L中值在(min,max)之间的节点
void Del_range(LinkList& L, int min, int max);
//8.给2个单链表,找出2个单链表的公共节点
LNode* Find_SameNode(LinkList A, LinkList B);
//9.给定一个带头节点的单链表,递增输出各个节点的值,并释放节点空间
//思路?先找到单链表中元素最小的值,然后就删除该节点
void Del_Mins(LinkList& L);
//10.将单链表A分为2个单链表A,B。A中存原表中序号为奇数的节点,B中存原表中序号为偶数的节点。且保持相对位置不变
LinkList Split2LinkList10(LinkList& A);
//11.将单链表A{a1,b1,a2,b2,a3,b3}分解为A{a1,a2,a3} B{b3,b2,b1}。此题和上一题要求差不多只不过B中元素逆置了.这里B中就用头插法来实现,A中还是用尾插法完成
LinkList Split2LinkList11(LinkList& A);
//12.在有序的单链表中,删除值相同的节点(记得保留一个),
void Del_Same(LinkList& L);
//13.将2个有序递增的单链表AB合并成一个有序递减的单链表A
void MergeList(LinkList& A, LinkList& B);
//14.将2个有序单链表中的公共值节点拼成一个新的链表C。不要删除原来节点的值
LinkList Get_Common(LinkList A, LinkList B);
//15.求2个有序链表的并集,
LinkList Union(LinkList& la, LinkList& lb);
//16.判断一个链表是否是另一个链表的子链表,也就是字符串判断他的子串 好像是Java中的Contains函数??唉!!为了复习考研我竟然有大半年没有写Java了。
bool  Pattern(LinkList A, LinkList B);
//17.判断一个循环双链表是否对称
bool Symmetry(DSLinkList L);
//18.将2个循环单链表合并成一个循环单链表,保持相对位置不变
LinkList Link(LinkList& h1, LinkList& h2);
//19.依次输出循环单链表中的较小值。并删除最小值节点
void Del_MinAll(LinkList& L);

//==========================广大915真题篇==============================
//2019第二题,要求:将一个带头节点的单链表L中值重复的多余节点删除,(就是去重)
void DelDistincts(LinkList& L);
//==========================常用函数==============================
void PrintList(LinkList L);
void PrintList_NoHead(LinkList L);

#endif // !LINKLIST_H

 

二:头文件具体的实现

#include"LinkList.h"

//==========================单链表的基本操作==============================
//1.头插法建立单链表(带头结点,没有特殊说明默认是带头节点的)
LinkList List_Insert_Head(LinkList& L) {
    int arr[6] = { 1,2,3,4,5,6 };//将改数组插入到单链表中
    LNode* s;//待插入的节点
    int i = 0;
    L = (LinkList)malloc(sizeof(LNode));//创建头节点
    L->next = NULL;

    while (i < 6) {
        s = (LNode*)malloc(sizeof(LNode));
        s->data = arr[i++];
        s->next = L->next;//将L后的东西放在S后面,以避免丢失
        L->next = s;
    }

    return L;
}
//(不带头节点的)
LinkList List_Insert_NoHead(LinkList& L) {
    int arr[6] = { 1,2,3,4,5,6 };//将改数组插入到单链表中
    LNode* s;//待插入的节点
    int i = 0;
    while (i < 6) {
        if (i == 0) {
            L = (LinkList)malloc(sizeof(LNode));
            L->data = arr[i++];
            L->next = NULL;
        }
        else {
            s = (LNode*)malloc(sizeof(LNode));
            s->data = arr[i++];
            //s->next = L->next; //这样写出来的是1 6 5 4 3 2
            //L->next = s;
            s->next = L;
            L = s;
        }
    }

    return L;
}

//2.尾插法建立单链表
LinkList List_Insert_Tail(LinkList& L) {
    //int arr[6] = { 1,2,3,4,5,6 };//将改数组插入到单链表中
    int arr[6] = { 1,2,2,4,5,6 };//将改数组插入到单链表中

    L = (LinkList)malloc(sizeof(LNode));//创建头节点
    LNode* s, * r = L;//s为待插入的节点,r指向尾指针的
    int i = 0;

    while (i < 6) {
        s = (LNode*)malloc(sizeof(LNode));
        s->data = arr[i++];
        r->next = s;
        r = s;
    }

    r->next = NULL;//最后尾指针指向NULL
    return L;
}

//3.按序号查找节点
//如果输入的是0,就返回头节点,小于1退出,
LNode* GetElem(LinkList L, int i) {
    int j=1;//从1开始计数
    LNode* p = L->next;//p为工作指针

    if (i == 0)
        return L;//返回头节点
    if (i < 1)
        return NULL;

    while (p && j < i) {
        p = p->next;
        j++;
    }

    return p;//注意这里p,因为循环里面写的p=p->next
}

//4.按值查找节点
LNode* LocateElem(LinkList L, ElemType e) {
    LNode* p = L->next;
    while (p != NULL && p->data != e) {
        p = p->next;
    }

    return p;
}


//==========================课后习题======================================
//1.使用递归,删除不带头节点的单链表L中所有值为x的节点
//递归条件:当改节点值是x就删除在递归调用该函数,不是该节点就调用该节点的的next。
//递归退出条件:递归到最后一个节点就没了
void Del_X1(LinkList &L, ElemType e) {
    LNode* q;//待删除的节点

    if (L == NULL)
        return;

    if (L->data == e) {
        q = L;
        L = L->next;
        free(q);//释放该节点
        Del_X1(L, e);
    }
    else {
        Del_X1(L->next, e);
    }
}

//2.在带头节点的单链表L中,删除L中所有值为x的节点
void Del_X2(LinkList& L, ElemType e) {
    LNode *p = L->next;//p工作指针
    LNode* prep = L;//p的前驱
    LNode* q;//待删除的节点

    while (p) {
        //如果p是要删除的值
        if (p->data == e) {
            q = p;
            p=p->next;
            prep->next = p;//不写这一句就要断链了
            free(q);
        }
        else {
            prep = p;
            p = p->next;
        }
    }
}

//3.从尾到头输出带头结点的单链表L中的所有节点值;
void R_Print3(LinkList L) {
    //使用递归
    //if (L) {
    //    R_Print3(L->next);
    //}
    //if(L)
    //    printf("%d ,", L->data);
    if (L->next!=NULL) {
        R_Print3(L->next);
    }

    printf("%d ,", L->data);
}

//4.删除带头结点的单链表L中最小值的节点高效方法(该最小值节点唯一)
void Del_Min4(LinkList& L) {
    //这个不是有序的,我还打算用二分法找最下值元素了,可以吗?? 哦哦,也不可以哈,顺序存储才得行哈!!发散思维到此结束
    LNode* p = L->next, *prep = L;//p prep视为工作指针
    LNode* minp = p, * prepmin = prep;//分别保存最下值的节点以及他的前驱
    while (p) {
        if (p->data < minp->data) {
            //p小于minp
            minp = p;
            prepmin = prep;
        }

        prep = p;
        p = p->next;
    }
    //找到了最小值的节点以及他的前驱
    prepmin->next = minp->next;
    free(minp);

}

//5.带头结点的单链表逆置
void Reverse5(LinkList& L) {
    //使用头插法的方法就行了
    LNode* p = L->next, * r;//p为工作指针, r为插入之后的尾指针
    L->next = NULL;//这里就将L->next置空

    while (p != NULL) {
        r = p->next;
        p->next = L->next;
        L->next = p;
        p = r;
    }
}

//6.使带头节点的单链表有序(有点陌生,许多看)
//使用了直接插入排序的思想,1:pre为有序部分的单链表遍历时的工作指针,遍历完一遍之后的结果是指向第一个大于待插入节点值的前驱元素,
//                            2:找到合适的pre之后,就插入p(无序部分的工作指针)的值,插入成功之后p后移,直到p遍历完成
void Sort_LinkList6(LinkList& L) {
    LNode* p=L->next, * pre;//p为无序断的工作指针,pre找到插入的合适位置的前驱 的工作指针
    LNode* r = p->next;//保证p不断链
    p->next = NULL;
    p = r;//执行第二个节点

    while (p != NULL) {
        r = p->next;
        pre = L;

        //pre的后继有元素,pre后继元素的值小于p的值,pre就向下移
        while (pre->next != NULL && pre->next->data < p->data) {
            pre = pre->next;
        }
        p->next = pre->next;
        pre->next = p;
        
        p = r;//扫描表中剩下的节点
    }
}

//7.删除无序带头节点的单链表L中值在(min,max)之间的节点
void Del_range(LinkList& L, int min, int max) {
    //通过2个指针来实现
    LNode* p = L->next, * pre = L;//p为工作指针,pre为它的前驱
    LNode* q;//待删除的节点
    while (p != NULL) {
        if (p->data > min&& p->data < max) {
            q = p;
            p = p->next;
            pre->next = p;//防止断链
            free(q);//删除
        }
        else {
            pre = p;
            p = p->next;
        }
    }
}

//8.给2个单链表,找出2个单链表的公共节点,就像一个躺着的Y 
//思路:先找到比较长的单链表,从左向右遍历,遍历到和短的单链表长度一样适合,在同时遍历2个单链表,每次遍历的时候就比较地址
/*                    0x0001 ->next 0x0004 ->next
                                                \
地址表示:                                          ———— 0x0008 ->next 0x0012 ->next 0x0000
                                                /
      0x0002 ->next 0x0003 ->next 0x0005 ->next
*/
LNode* Find_SameNode(LinkList A, LinkList B) {
    //这里就直接赋值A B的长度了,没有写length(A)函数,
    int Alen = 4, Blen = 5;//这里按照上面图来赋值的
    LinkList longList, shortList;//分别指向较长的单链表和较短的单链表
    int dist;//2个链表长度差

    if (Alen > Blen) {
        longList = A->next;
        shortList = B->next;
        dist = longList - shortList;
    }
    else {
        longList = B->next;
        shortList = A->next;
        dist = longList - shortList;
    }

    while (dist--)
        longList = longList->next;//后移dist(AB长度差),使之同步
    
    //开始寻找公共节点
    while (longList != NULL) {
        if (longList == shortList)//比较的是地址
            return longList;//返回二者之一均可
        else {
            longList = longList->next;
            shortList = shortList->next;
        }//if结束

    }

    return NULL;
}

//9.给定一个带头节点的单链表,递增输出各个节点的值,并释放节点空间
//思路?先找到单链表中元素最小的值,然后就删除该节点。(这里注意的是在找最小值节点的时候,每次都是从第一个节点开始找)
void Del_Mins(LinkList& L) {
    LNode* p,* pre, * q;//p工作指针,pre为待删除节点的前驱,q为待删除的节点
    
    while (L->next != NULL) {
        //每次都会少一个最小值的节点
        pre = L;
        p = pre->next;//每次都从第二个元素开始寻找,第一个元素都使pre->next(也就是最小值的元素)
        while (p->next!=NULL) {//(助记:每次最开始的一次循环是:第二个元素和第一个元素比较大小)

            if (p->next->data < pre->next->data) {
                pre = p;//将最小值的前驱节点更新
            }

            p = p->next;
        }

        //通过这个循环找到了最小值节点的前驱
        q = pre->next;
        printf("%d, ", q->data);
        pre->next = q->next;//删除了该节点
        free(q);
        
    }
    //最后释放头节点
    free(L);
}

//10.将单链表A分为2个单链表A,B。A中存原表中序号为奇数的节点,B中存原表中序号为偶数的节点。且保持相对位置不变
LinkList Split2LinkList10(LinkList& A) {
    int i = 0;//用来判断是奇数还是偶数位序的节点
    //创建B链表
    LinkList B = (LinkList)malloc(sizeof(LNode));
    B->next = NULL;
    LNode* ra = A, * rb = B;//ra,rb分别是AB的尾节点,因为要保持先对位置不变,就使用尾插法
    LNode* p = A->next;//p为工作指针
    
    A->next = NULL;//A链表置空,以便插入。不要误以为A链表之后的东西就没了,其实p一直保存起来的了
    while (p != NULL) {
        i++;
        if (i % 2 == 0) {//偶数插入B中
            rb->next = p;
            rb = p;
        }
        else {
            ra->next = p;
            ra = p;
        }
        p = p->next;
    }
    //插入成功,再将A B 2链表的尾节点置空
    ra->next = NULL;
    rb->next = NULL;

    return B;

}

//11.将单链表A{a1,b1,a2,b2,a3,b3}分解为A{a1,a2,a3} B{b3,b2,b1}。此题和上一题要求差不多只不过B中元素逆置了.这里B中就用头插法来实现,A中还是用尾插法完成
LinkList Split2LinkList11(LinkList& A) {
    LinkList B = (LinkList)malloc(sizeof(LNode));
    B->next = NULL;
    LNode* p = A->next, * q;//p为工作指针 。当p节点插入到B中的时候,就用q来防止断链的
    LNode* ra = A;//为A的尾节点

    while (p != NULL) {
        ra->next = p;
        ra = p;//A进行尾插法
        
        p = p->next;
        q = p->next;//即将插到B中,防止断链
        p->next = B->next;
        B->next = p;

        p = q;//p插入成功之后,又接回到直接断链的位置
    }

    //循环结束,A链表尾指针置NULL
    ra->next = NULL;

    return B;
}

//12.在有序的单链表中,删除值相同的节点(记得保留一个),
void Del_Same(LinkList& L) {
    LNode* p = L->next, * q;//q为要删除的重复节点
    if (p == NULL)
        return;

    while (p->next != NULL) {
        q = p->next;//同时q也是p的后继
        if (p->data == q->data) {
            p->next = q->next;
            free(q);
        }
        else {
            p = p->next;
        }
    }
}

//13.将2个有序递增的单链表AB合并成一个有序递减的单链表A
void MergeList(LinkList &A, LinkList &B) {
    LNode* pa = A->next, * pb = B->next;//分别是AB的工作指针
    LNode* r;//防止断链的

    A->next = NULL;//将A置空,以便插入元素到里面
    while (pa && pb) {//当2链表均不为空时候,循环
        if (pa->data <= pb->data) {//如果pa的元素小于pb,就将pa使用头插法插到A中
            r = pa->next;//防止断链
            pa->next = A->next;
            A->next = pa;

            pa = r;//恢复pa的工作指针性质
        }
        else {
            r = pb->next;
            pb->next = A->next;
            A->next = pb;

            pb = r;
        }
    }

    //通常情况下有一个链表会有剩余,
    if (pa)
        pb = pa;//如果pa不为空,pb就执行pa,(默认将pb认为指向不为空的那个链表)

    while (pb) {
        r = pb->next;
        pb->next = A->next;
        A->next = pb;

        pb = r;
    }

    free(B);
}

//14.将2个有序单链表中的公共值节点拼成一个新的链表C。不要删除原来节点的值
//思路?step1:2个链表是有序的,可以从第一个元素一次比较A B2表中的元素。
//        step2:如果元素值不相等,则值小的指针后移。
//        step3:如果元素相等,创建一个值等于2节点的新节点,再使用尾插法插入的C中,最后2工作指针都后移一位
LinkList Get_Common(LinkList A, LinkList B) {
    LNode* p = A->next, * q = B->next;//p q分别为A.B的工作指针
    LNode* r;//为C的尾节点,进行尾插法使用的
    LNode* s;//为值相同的新节点
    LinkList C = (LinkList)malloc(sizeof(LNode));
    r = C;

    while (p != NULL && q != NULL) {
        if (p->data < q->data) {
            p = p->next;
        }
        else if (p->data > q->data) {
            q = q->next;
        }
        else {
            s = (LNode*)malloc(sizeof(LNode));
            //将值相同的节点复制到s的数据域中
            s->data = p->data;
            r->next = s;
            r = s;
            //p q同时后移
            p = p->next;
            q = q->next;
        }
    }
    r->next = NULL;
    return C;
}

//15.求2个有序链表的并集,
//思路:1:使用归并的方法,设置2个工作指针pa,pb,对2个链表进行归并并扫描,
//        2:只有同时出现在2个集合中的元素链接到结果表中,且仅保留一个其他节点全部释放掉,
//        3:当其中一个节点遍历完之后,释放另一个剩下表的全部节点
LinkList Union(LinkList& la, LinkList& lb) {
    LNode* pa = la->next;
    LNode* pb = lb->next;//工作指针pa pb
    LNode* u;//待删除的节点
    LNode* pc = la;//结果表中当前合并节点的前驱指针(这里的结果表示la哦。不要搞错了)
    
    while (pa && pb) {
        if (pa->data == pb->data) {
            //交集放入到尾插到结果表中
            pc->next = pa;
            pc = pa;

            pa = pa->next;
            u = pb;//删除B中的相同节点
            pb = pb->next;
            free(u);
        }
        else if (pa->data < pb->data) {
            u = pa;
            pa = pa->next;
            free(u);
        }
        else {
            u = pb;
            pb = pb->next;
            free(u);
        }
    }

    while (pa) {
        u = pa;
        pa = pa->next;
        free(u);
    }

    while (pb) {
        u = pb;
        pb = pb->next;
        free(u);
    }

    pc->next = NULL;//尾插法的嘛。记得尾节点指向NULL
    free(lb);//记得删除lb,不是删除la,也不应该删除la,因为是把节点插入到la中的
    
    return la;

}

//16.判断一个链表是否是另一个链表的子链表(没有头节点的),也就是字符串判断他的子串 好像是Java中的Contains函数??唉!!为了复习考研我竟然有大半年没有写Java了。
bool  Pattern(LinkList A, LinkList B) {
    LNode* p = A;
    LNode* pre = p;//记录每趟比较链表中的开始节点
    LNode* q = B;

    while (p && q) {
        if (p->data == q->data) {
            p = p->next;
            q = q->next;
        }
        else {
            pre = pre->next;
            p = pre;//p又为A链表中的新开始比较节点
            q = B;//q从B链表第一个节点开始
        }
    }

    if (q == NULL)
        return true;//q为空说明B就是A的子序列
    else
        return false;
}

//17.判断一个循环双链表是否对称
bool Symmetry(DSLinkList L) {
    DSNode* p = L->next, * q = L->prior;//p从左向右遍历,q从右向左遍历
    while (p != q && p->next != q) {//当q p不等,或者p q相邻就退出循环
        if (p->data == q->data) {
            p = p->next;
            q = q->prior;
        }
        else {
            return false;//有一个不相同就是不对称的
        }
    }

    return true;
}

//18.将2个循环单链表合并成一个循环单链表,保持相对位置不变
LinkList Link(LinkList& h1, LinkList& h2) {
    //step1:找到2个循环单链表的尾节点
    LNode* p, * q;
    p = h1;
    q = h2;
    while (p->next != h1)
        p = p->next;
    while (q->next != h2)
        q = q->next;

    //step2:将h1的尾节点指向h2的头节点,h2的尾节点指向h1的头节点
    p->next = h2;
    q->next = h1;

    return h1;
}

//19.依次输出循环单链表中的较小值。并删除最小值节点
void Del_MinAll(LinkList& L) {
    LNode* p, * pre, * minp, * minpre;//p为工作指针,pre为它的前驱,minp指向最小值的节点,minpre为它的前驱
    while (L->next = L) {//循环单练表的嘛
        p = L->next;
        pre = L;

        minp = p;
        minpre = pre;
        //找最小值
        while (p != L) {
            if (p->data < minp->data) {
                minp = p;
                minpre = pre;
            }
            pre = p;
            p = p->next;
        }
        printf("%d, ", minp->data);
        minpre->next = minp->next;//删除该节点
        free(minp);
    }

    free(L);//释放头节点
} 


//==========================广大915真题篇==============================
//2019第二题,要求:将一个带头节点的单链表L中值重复的多余节点删除,(就是去重)
void DelDistincts(LinkList& L) {
    LNode* p, * pre, * q;//p为工作指针,pre为它的前驱,q为待删除的节点
    pre = L;
    p = L->next;
    while (p) {
        if (p->data == pre->data) {
            q = p;
            p = p->next;
            pre->next = p;
            free(q);
        }
        else {
            pre = p;
            p = p->next;//如果pre和p不同,则同时后移
        }
    }
}


//==========================常用函数==============================
void PrintList(LinkList L) {
    LNode* p = L->next;
    while (p) {
        printf("%d ,", p->data);
        p = p->next;
    }

    printf("\n");
}

void PrintList_NoHead(LinkList L) {
    while (L) {
        printf("%d ,", L->data);
        L = L->next;
    }

    printf("\n");
}

 

三:主函数如下

#include"LinkList.h"

int main() {
    LinkList L;
    LNode* temp;

    //==========================单链表的基本操作==============================
    //1.头插法
    //List_Insert_Head(L);
    //List_Insert_NoHead(L);
    //2.尾插法
    List_Insert_Tail(L);
    //3.按序号查找节点
    //temp =GetElem(L, 3);
    //printf("%d\n", temp->data);
    //4.按值查找节点
    //LocateElem(L, 3);


    //==========================课后习题======================================
    //1.使用递归,删除不带头节点的单链表L中所有值为x的节点(测试记得使用头插法不带头节点的函数)
    //Del_X1(L, 3);
    //2.在带头节点的单链表L中,删除L中所有值为x的节点
    //Del_X2(L, 3);
    //3.从尾到头输出带头结点的单链表L中的所有节点值;
    //R_Print3(L);
    //printf("\n");
    //4.删除带头结点的单链表L中最小值的节点高效方法(该最小值节点唯一)
    //Del_Min4(L);
    //5.带头结点的单链表逆置
    //Reverse5(L);
    //6.使带头节点的单链表有序
    //Sort_LinkList6(L);
    //7.删除无序带头节点的单链表L中值在(min,max)之间的节点
    //Del_range(L,2 ,5);
    //8.给2个单链表,找出2个单链表的公共节点,就像一个躺着的Y 
    //注意:怎么说了,这个单链表我又不能手动赋指定地址值,所以就实现不了。要想实现,就将找公共节点改为公共值的节点,节点值看成节点地址值。
    //我也懒得写了,考试也考不到这里来,再过25分钟,距离考研只有43天了我线性代数都还没有复习完,我靠( ‵o′)凸。算了,洗漱早睡,明早看线性代数,
    ////Find_SameNode(L,L);不用打开,跑不起来的
    //9.给定一个带头节点的单链表,递增输出各个节点的值,并释放节点空间
    //思路?先找到单链表中元素最小的值,然后就删除该节点
    //Del_Mins(L);
    //10.将单链表A分为2个单链表A,B。A中存原表中序号为奇数的节点,B中存原表中序号为偶数的节点。且保持相对位置不变
    //LinkList B = Split2LinkList10(L);//(L相当于A)
    //printf("B链表输入如下:");
    //PrintList(B);
    //printf("A链表输入如下:");
    //11.将单链表A{a1,b1,a2,b2,a3,b3}分解为A{a1,a2,a3} B{b3,b2,b1}。此题和上一题要求差不多只不过B中元素逆置了.这里B中就用头插法来实现,A中还是用尾插法完成
    //LinkList B = Split2LinkList11( L);
    //printf("B链表输入如下:");
    //PrintList(B);
    //printf("A链表输入如下:");
    //12.在有序的单链表中,删除值相同的节点(记得保留一个)
    //测试的时候,将头插法的那个数组改一下
    //Del_Same(L);
    //13.将2个有序递增的单链表AB合并成一个有序递减的单链表A
    //LinkList B;
    //List_Insert_Tail(B);
    //MergeList(L,B);
    //14.将2个有序单链表中的公共值节点拼成一个新的链表C。不要删除原来节点的值
    //LinkList C = Get_Common(L,L);
    //PrintList(C);
    //15.求2个有序链表的并集,
    //LinkList B;
    //List_Insert_Tail(B);
    //LinkList C = Union(L, B);
    //PrintList(C);
    //16.判断一个链表是否是另一个链表的子链表,也就是字符串判断他的子串 好像是Java中的Contains函数??唉!!为了复习考研我竟然有大半年没有写Java了。
    //List_Insert_NoHead(L);
    // printf("%s\n", Pattern(L, L)?"是":"不是");
    //17.判断一个循环双链表是否对称.不能测试,记住代码就行了
    //// Symmetry(L);
    //18.将2个循环单链表合并成一个循环单链表,保持相对位置不变. 不能测试,记住代码就行了
    ////Link(h1,h2)
    //19.依次输出循环单链表中的较小值。并删除最小值节点
    ////Del_MinAll(L);
    //后面的不写了,广大考不了那么难,我的高数都还复习完,时间宝贵

    //PrintList(L);
    //PrintList_NoHead(L);

    //==========================广大915真题篇==============================
    //2019第二题,要求:将一个带头节点的单链表L中值重复的多余节点删除,(就是去重)
    DelDistincts(L);

    PrintList(L);
    return 0;
}

 

posted @ 2019-11-09 21:32  大魔王阿黎  阅读(577)  评论(0编辑  收藏  举报