数据结构之链表【参考25wd书】

 头文件(针对vs2022做了相应更改便于观看)

#include <stdio.h>
#include <stdbool.h>
#include <iostream>
#include <stdbool.h>
#include <algorithm>
#include <math.h>
#pragma warning(disable:4996)//忽略scanf,printf的检查
#pragma warning(disable:6011)//忽略空指针的赋值警告
using namespace std;

结构体定义

typedef struct LNode {

    int data;
    struct LNode* Next;
   
}LNode, * LinkList;
typedef struct DNode {//用于双链表,学习单链表时不必理会

    int data;
    struct DNode* Next;
    struct DNode* prior;//前驱指针
}DNode, * DLinklist;

初始化

bool InitList(LinkList& l)
{
    l = (LNode*)malloc(sizeof(LNode));
    if (l == NULL)
        return false;
    l->Next = NULL;
    return  true;
}
bool InitDlinkList(DLinklist& l)
{
    l = (DNode*)malloc(sizeof(DNode));
    if (l == NULL)
        return false;
    l->prior = NULL;
    l->Next = NULL;
    return true;;

}

插入

bool ListInsert(LinkList& l, int i, int e) {//带头结点的按位序插入,e为插入的元素,i为插入位置
    if (i < 1)
        return false;
    LNode* p;
    int j = 0;//位序的计数器
    p = l;//从头结点开始
    while (p != NULL && j < i - 1)//头节点可看作第0个,找i-1
    {
        p = p->Next;
        j++;

    }
    if (p == NULL)
        return false;//i不合法
    LNode* s = (LNode*)malloc(sizeof(LNode));
    s->data = e;
    s->Next = p->Next;
    p->Next = s;//顺序不能颠倒,会导致原先后面链表丢失
    return true;

    //时间:o(n)

}
bool InserNextDNode(DNode* p, DNode* s)//双链表插入,s插到p后面
{
    if (p == NULL || s == NULL)
        return false;
    s->Next = p->Next;
    if(p->Next!=NULL)//p为末节点的处理
    p->Next->prior = s;
    s->prior = p;
    p->Next = s;
    return true;
}

bool nohead_ListInsert(LinkList& l, int i, int e) {//不带头结点的按位序插入,e为插入的元素,i为插入位置
    if (i < 1)
        return false;
    if (i == 1)//头结点处特殊处理即可
    {
        LNode* s = (LNode*)malloc(sizeof(LNode));
        s->data = e;
        s->Next = l;
        l = s;
        return true;
    }
    LNode* p;
    int j = 1;//位序的计数器
    p = l;//从第一个结点开始
    while (p != NULL && j < i - 1)//找i-1
    {
        p = p->Next;
        j++;

    }
    if (p == NULL)
        return false;//i不合法
    LNode* s = (LNode*)malloc(sizeof(LNode));
    s->data = e;
    s->Next = p->Next;
    p->Next = s;//顺序不能颠倒,会导致原先后面链表丢失
    return true;

    //时间:o(n)

}
bool InserNextNode(LNode* p, int e)//指定节点p的后插,e为插入元素
{
    if (p == NULL)
        return false;
    LNode* s = (LNode*)malloc(sizeof(LNode));
    if (s == NULL)
        return false;
    s->data = e;
    s->Next = p->Next;
    p->Next = s;
    return true;
}
bool InserPriorNode(LNode* p, int e)//指定节点p的前插,e为插入元素
{
    if (p == NULL)
        return false;
    LNode* s = (LNode*)malloc(sizeof(LNode));
    if (s == NULL)
        return false;
    s->Next = p->Next;
    p->Next = s;
    s->data = p->data;
    p->data = e;     //用新的节点s替代原本的p,把原本的p当作是前插的节点罢了
    //时间o(1)
    //给了头节点去从头找p的前插的话,时间o(n)
    return true;
}

删表

void DestoryList(DLinklist& l)
{
    while (l->Next != NULL)
        DeleteNextDNode(l);
    free(l);
    l = NULL;

}

删点

bool ListDelete(LinkList& l, int i, int& e)//按位删除,带头结点,i表示第i个,e表示删除位置的data

{
    if (i < 1)
        return false;
    LNode* p=l;
    int j = 0;
    while (p != NULL && j < i - 1)
    {
        p = p->Next;
        j++;


    }
    if (p == NULL)
        return false;
    if (p->Next == NULL)
        return false;
    LNode* q = p->Next;
    p->Next = q->Next;
    e = q->data;
    free(q);
    return true;

    //时间o(n)
}
bool DeleteNode(LNode* p)//指定节点删除
{
    if (p == NULL)
        return false;
    LNode* q = p->Next;
    if (q == NULL)
    {
        cout << "此方法不可行,p已是最后节点,q此时会报错,此时应采用头节点找p前驱的法,o(n)";
        return false;

    }
    p->data = p->Next->data;
    p->Next = q->Next;
    free(q);
    return true;
    //仍是用后继节点代替p删除,从而达成删除p的效果,时间o(1)


}
bool DeleteNextDNode(DNode* p)//删除p的后续节点
{
    if (p == NULL)
        return false;
    DNode* q = p->Next;
    if (q == NULL)
        return false;
    p->Next = q->Next;
    if (q->Next != NULL)
        q->Next->prior = p;
    free(q);
    return true;


}

查表

LNode *GetElem(LinkList l,int i)//按位查找,与上述代码片段相同,o(n)
{
    if (i < 0)
        return NULL;
    LNode* p=l;
    int j = 0;
    while (p != NULL && j < i )
    {
        p = p->Next;
        j++;

    }
    return p;

}
LNode* LocalElem(LinkList l, int e)//按值查找,o(n)
{

    LNode* p = l->Next;
    while (p != NULL &&p->data!=e)
    {
        p = p->Next;

    }
    return p;

}

表长

int Length(LinkList l)//统计链表长
{
    int len = 0;
    LNode* p = l;
    while (p->Next != NULL)
    {
        p = p->Next;
        len++;//时间  o(n)
    }
    return len;

}

建表(头插,尾插)

//尾插法:1.可以不断调用ListInsert插入最后一位,但双重循环,时间上为o(n^2)
LinkList List_TailInsert(LinkList& L)//课本尾插法
{
    int x;
    L = (LinkList)malloc(sizeof(LNode));//头
    LNode* s, * r = L;
    cin >> x;
    while (x != 9999)//结束标志
    {
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        r->Next = s;
        r = s;
        cout << x;



    }
    r->Next = NULL;
    return L;



}
LinkList List_headInsert(LinkList& l)//头插,也就是后插 ,用于逆置
{
    LNode* s;
    int x;
    l = (LinkList)malloc(sizeof(LNode));//头
    l->Next = NULL;//此句为了清除脏数据
    cin >> x;
    while (x != 9999)
    {
        s = (LNode*)malloc(sizeof(LNode));//逆置链表的思想,建议实操
        s->data = x;//逆置链表的思想
        s->Next = l->Next;//逆置链表的思想
        l->Next = s;//逆置链表的思想
        cin >> x;
    }
    return l;
}

王道题1-14

//页数43 p1-13
bool  p1(LinkList head, int e)
{
    while (head->Next!= NULL)
    {
        if (head->Next->data == e)
        {
            LNode* s = head->Next;
            if (s->Next == NULL)
            {
                free(s);
                return true;

            }
            head->Next = s->Next;
            free(s);
            continue;

        }
        head = head->Next;

    }
   
   
    return true;



}
bool p2(LinkList head)
{     int minnum = head->Next->data;
       LNode* prior=NULL; LNode* cur=NULL; 
       
     
    while (head->Next != NULL)
    {
       

        if (head->Next->data < minnum)
        {
            minnum =head->Next->data;
             prior = head;
             cur = head->Next;

        }
        head = head->Next;

    }
    if (prior != NULL && cur != NULL)
    {
        prior->Next = cur->Next;
        free(cur);
        return true;

    }
    

    return false;


}

LinkList p3(LinkList l)
{
    LNode* cur = l->Next;
    LNode* pn = NULL;
    l->Next = NULL;
    while (cur!=NULL)
    {   
        pn = cur->Next;
        cur->Next = l->Next;
        l->Next = cur;
        cur = pn;

     }
    return  l;



}


bool  p4(LinkList head, int n,int N)
{
    while (head->Next != NULL)
    {
        if (head->Next->data > n && head->Next->data < N)
        {
            LNode* s = head->Next;
            if (s->Next == NULL)
            {
                free(s);
                return true;

            }
            head->Next = s->Next;
            free(s);
            continue;

        }
        head = head->Next;

    }


    return true;



}
void p6(LinkList temp)//原题a,b的大小为n,故原链表元素必为偶数,此算法也仅是考虑了偶数。王道中是单节点更加简便,但时间复杂度都为o(n)
{
    LNode* prior = temp->Next;
    LNode* cur = prior->Next;
    temp->Next = NULL;
    if (prior == NULL || cur == NULL)
        return;
    LNode*a= (LinkList)malloc(sizeof(LNode));
    LNode*b = (LinkList)malloc(sizeof(LNode));
    LNode* tail = a;
    LNode* head = b;
    b->Next = NULL;
   while (prior&&cur )
    {
        tail->Next = prior;//weicha
        tail = prior;//weicha
        prior = cur->Next;

        cur->Next = head->Next;//toucha
        head->Next = cur;//toucha 
        if (!prior) break;
        cur = prior->Next;
      
       } 
    tail->Next = NULL;
    print(a);
    cout << endl;
    print(b);

}
void p7(LinkList temp)//前提为排序列表,记录当前值即可。

{
    LNode* prior = temp->Next;
    if (!prior)
     return;
    int num = prior->data;
    LNode* cur = prior->Next;
    if (cur == NULL)
    {
        cout << prior->data;
        return;

    }
    while (cur->Next!= NULL)
    {
        if (cur->data == num)
        {
            prior->Next = cur->Next;
            LNode* tmp = cur;
            cur = cur->Next;
            free(tmp);
            continue;

        }
        cur = cur->Next;
        prior = prior->Next;
        num = prior->data;
    }


    print(temp);
    cout << endl;


}
void p8(LinkList a, LinkList b)
{
    LNode* p = a->Next;
    LNode* q = b->Next;

    LNode*c = (LinkList)malloc(sizeof(LNode));
    LNode* r = c;
    while (p && q)
    {
        if (p->data < q->data)
        {
            p = p->Next;
        }
        else  if(p->data > q->data)  q = q->Next;
        else {
            LNode* s = (LinkList)malloc(sizeof(LNode));
            s->data = p->data;
            r->Next = s;
            r = s;
            p = p->Next;
            q = q->Next;



        }



    }

    r->Next = NULL;
    print(c);
    cout << endl;


}
LinkList p9(LinkList& a, LinkList& b)
{

    LNode* p = a->Next;
    LNode* q = b->Next;
    LNode* u, * pc = a;
    while (p && q)
    {
        if (p->data == q->data)
        {
            pc->Next = p;
            pc = p;
            p = p->Next;
            u = q;
            q = q->Next;
            free(u);


        }
        else if (p->data < q->data)
        {
            u = p;p = p->Next;
            free(u);



         }
        else {
            u = q;
            q = q->Next;
            free(u);

        }



    }

    while (p)
    {
        u = p;
        p = p->Next;
        free(u);



    }
    while (q)
    {

        u = q;
        q = q->Next;
        free(u);

    }
    pc->Next = NULL;
    free(q);
    return a;



}
bool p10(LinkList a, LinkList b)//kmp的雏形,这里偷懒直接暴力了,王道答案也是暴力
{   
    LNode* p = a->Next;
    LNode* q = b->Next;
    LNode* prior = p;
    while (p && q)
    {
        if (p->data == q->data)
        {
            p = p->Next;
            q = q->Next;


        }
        else {
            prior = prior->Next;
            p = prior;
            q = b->Next;


        }
        if (q==NULL)
            return  true;
        else
            return false;

    }

}
bool p11(DLinklist l)//从头指针开始一个向左一个向右,相等就继续不等就判假即可,样例就不给出了。
{
    DNode* p = l->Next;
    DNode* q= l->prior;
    while (p != q && q->Next != p)
    {
        if (p->data == q->data)
        {
            p = p->Next;
            q = q->Next;



        }
        else
            return false;


    }


    return true;



}
LinkList  p12(LinkList& a, LinkList& b)//a,b默认为循环单链表,循环链表的题很少用样例重在思想了。
{//一个选择题的思想,找到两个单循环表的尾巴相连再做一些细节处理
    LNode* p, * q;
    p = a;
    while (p->Next != NULL)
        p = p->Next;
    q = b;
    while (q->Next != NULL)
        q = q->Next;
    p->Next = b;
    q->Next = a;
    return a;



}
typedef struct DNode13 {//13题双链表,初始化里记得freq置零,此处不演示初始化也不加样例,读者自行实现即可

    int data;
    int freq=0;
    struct DNode13* Next;
    struct DNode13* prior;//前驱指针
}DNode13, * DLinklist13;
DLinklist13  p13(DLinklist13& l, int e)
{
    DLinklist13  p = l->Next;
    DLinklist13  q;//用来记录找的位置
    while (p && p->data != e)
        p = p->Next;
    if (!p)
    {
        cout << "ERROR";
        exit(-1);

    }
    else {
        p->freq++;
        if (p->prior == l || p->prior->freq > p->freq)
            return p;//p在首或者p比前面少,都说明现在的位置已经是要求的,直接返回
        if (p->Next)p->Next->prior = p->prior;
        p->prior->Next = p->Next;
        q = p->prior;
        while (q != l && q->prior->freq <= p->freq)//q从p的prior位置往前找,要么找到头要么找到第一个比他freq值大的地方,在其后面插入p;
            q = q->prior;
        p->Next = q->Next;
        p->prior = q;
        q->Next->prior = p;
        q->Next = p;



    }
    return p;




}
void p14(LinkList l, int k)//转换成循环单链表,找到尾节点后断开,注:l不含头节点
{
    LNode* p = l;
    int lenth=1;
    while (p->Next != NULL)
    {
        p = p->Next;
        lenth++;
    }
    p->Next = l;
    p = l;
    for (int i = 1;i < lenth - k;i++)
    {
        p = p->Next;

    }
    l = p->Next;
    p->Next = NULL;
    nohead_print(l);

}

王道题15-20

LinkList p15(LinkList head)//Map映射法,或者答案的双指针法,但是环入口不好找,a=nr-x
{
    LinkList fast = head;
    LinkList slow = head;
    while (fast != NULL && fast->Next != NULL)
    {
        slow = slow->Next;
        fast = fast->Next->Next;
        if (slow == fast)
            break;

    }
    if( fast->Next == NULL||fast == NULL )
     return NULL;
    LinkList ph = head;
    LinkList ps = slow;
    while (ph != ps)
    {
        ph = ph->Next;
        ps = ps->Next;

    }//a=nr-x
    return ph;

}
int p16(LinkList head)//注:无头指针的链表
{
    LNode* fast = head->Next;
    LNode* slow = head;
    while (fast->Next != NULL && fast != NULL)
    {
        slow = slow->Next;
        fast = fast->Next->Next;
    }
    LNode* s = slow->Next;
    LNode* tmp;
    LNode* newhead = (LinkList)malloc(sizeof(LNode));//我带了头节点,带不带都行
    newhead->Next = NULL;
    while (s)
    {
        tmp = s->Next;
        s->Next = newhead->Next;
        newhead->Next = s;
        s = tmp;
    }
    int max = 0;
    LNode* first = head;
    LNode* second = newhead->Next;
    while (first &&second)
    {
        if ((first->data + second->data) > max)
            max = first->data + second->data;
        first = first->Next;
        second = second->Next;


    }
    return max;


}
int p17(LinkList head,int k)
{
    LinkList p = head;
    LinkList q = head;
    int count = 0;
    while (p)
    {
        if (count < k)
        {
            count++;
            p = p->Next;
        }
        else
        {
            q = q->Next;
            p = p->Next;

        }


    }
    if (count < k)
        return 0;
    else {
        cout << q->data;
        return 1;
    }







}
LinkList p18(LinkList str1, LinkList str2)//第五题的具体实现,不再详解
{
    int m = Length(str1);
    int n = Length(str2);
    LinkList p, q;
    for (p = str1;m > n;m--)
        p = p->Next;
    for (q = str2;m < n;n--)
        q = q->Next;
    while (p->Next != NULL && p->Next != q->Next)
    {
        p = p->Next;
        q = q->Next;
    }
    return p->Next;
}

void p19(LinkList head, int n)
{
    LinkList p = head;
    LinkList r;
    int* q, m;
    q = (int*)malloc(sizeof(int) * (n + 1));
    for (int i = 0;i < n + 1;i++)
        *(q + i) = 0;
    while (p->Next != NULL)
    {
        m = abs(p->Next->data);
        if (*(q + m) == 0)
        {
            *(q + m)=1;
            p = p->Next;

        }
        else
        {
            r = p->Next;
            p->Next = r->Next;
            free(r);




        }




    }

    free(q);

}
void p20(LinkList head)
{
    LNode* fast = head->Next;
    LNode* slow = head;
    while (fast->Next != NULL && fast != NULL)
    {
        slow = slow->Next;
        fast = fast->Next->Next;
    }
    fast = slow->Next;
    slow->Next = NULL;
    LinkList tmp;
    while (fast)
    {
        tmp = fast->Next;
        fast->Next = slow->Next;
        slow->Next = fast;
        fast = tmp;

    }
    LinkList s;
    LinkList r;
    s = head->Next;
    fast = slow->Next;
    while (fast)
    {
        r = fast->Next;
        fast->Next = s->Next;
        s->Next = fast;
        s = fast->Next;
        fast = r;

    }
}

全文(部分样例见最后)

#include <stdio.h>
#include <stdbool.h>
#include <iostream>
#include <stdbool.h>
#include <algorithm>
#include <math.h>
#pragma warning(disable:4996)//忽略scanf,printf的检查
#pragma warning(disable:6011)//忽略空指针的赋值警告
#pragma warning(disable:6001)
#define MaxSize 10
#define List_Lenth 100
using namespace std;
typedef struct LNode {//单链表

    int data;
    struct LNode* Next;
   
}LNode, * LinkList;
typedef struct DNode {//用于双链表,学习单链表时不必理会

    int data;
    struct DNode* Next;
    struct DNode* prior;//前驱指针
}DNode, * DLinklist;

typedef struct {//静态链表,以数组方式表示链表,next存放下一个数据的数组下标,eg:操作系统的FAT文件分配表
    int data;
    int next;//以-1作为结束标志
}SLinkList[MaxSize];                        



bool InitList(LinkList& l)
{
    l = (LNode*)malloc(sizeof(LNode));
    if (l == NULL)
        return false;
    l->Next = NULL;
    l->data = -1;//头节点默认值,方便区分
    //l->Next=l;  //代表该单链表为循环单链表,即最后一个节点的next指向头节点,同时检查l-》next==l可确定循环单链表是否为空
    return  true;
}
bool InitDlinkList(DLinklist& l)
{
    l = (DNode*)malloc(sizeof(DNode));
    if (l == NULL)
        return false;
    l->prior = NULL;//l->prior = l ,循环双链表,让头尾节点相连,同时检查l-》next==l可确定循环双链表是否为空
    l->Next = NULL;//l->Next = l
    return true;;

}
bool ListInsert(LinkList& l, int i, int e) {//带头结点的按位序插入,e为插入的元素,i为插入位置
    if (i < 1)
        return false;
    LNode* p;
    int j = 0;//位序的计数器
    p = l;//从头结点开始
    while (p != NULL && j < i - 1)//头节点可看作第0个,找i-1
    {
        p = p->Next;
        j++;

    }
    if (p == NULL)
        return false;//i不合法
    LNode* s = (LNode*)malloc(sizeof(LNode));
    s->data = e;
    s->Next = p->Next;
    p->Next = s;//顺序不能颠倒,会导致原先后面链表丢失
    return true;

    //时间:o(n)

}
void print(LinkList L)//有头节点的链表打印
{
    while (L->Next != NULL)
    {
        cout << L->Next->data << " ";
        L = L->Next;

    }

}
void nohead_print(LinkList L)//无头节点的链表打印
{
    while (L!= NULL)
    {
        cout << L->data << " ";
        L = L->Next;

    }

}
bool InsertNextDNode(DNode* p, DNode* s)//双链表插入,s插到p后面
{
    if (p == NULL || s == NULL)
        return false;
    s->Next = p->Next;
    if(p->Next!=NULL)//p为末节点的处理,循环链表则不会出错
    p->Next->prior = s;
    s->prior = p;
    p->Next = s;
    return true;
}

bool nohead_ListInsert(LinkList& l, int i, int e) {//不带头结点的按位序插入,e为插入的元素,i为插入位置
    if (i < 1)
        return false;
    if (i == 1)//头结点处特殊处理即可
    {
        LNode* s = (LNode*)malloc(sizeof(LNode));
        s->data = e;
        s->Next = l;
        l = s;
        return true;
    }
    LNode* p;
    int j = 1;//位序的计数器
    p = l;//从第一个结点开始
    while (p != NULL && j < i - 1)//找i-1
    {
        p = p->Next;
        j++;

    }
    if (p == NULL)
        return false;//i不合法
    LNode* s = (LNode*)malloc(sizeof(LNode));
    s->data = e;
    s->Next = p->Next;
    p->Next = s;//顺序不能颠倒,会导致原先后面链表丢失
    return true;

    //时间:o(n)

}
bool InsertNextNode(LNode* p, int e)//指定节点p的后插,e为插入元素
{
    if (p == NULL)
        return false;
    LNode* s = (LNode*)malloc(sizeof(LNode));
    if (s == NULL)
        return false;
    s->data = e;
    s->Next = p->Next;
    p->Next = s;
    return true;
}
bool InserPriorNode(LNode* p, int e)//指定节点p的前插,e为插入元素
{
    if (p == NULL)
        return false;
    LNode* s = (LNode*)malloc(sizeof(LNode));
    if (s == NULL)
        return false;
    s->Next = p->Next;
    p->Next = s;
    s->data = p->data;
    p->data = e;     //用新的节点s替代原本的p,把原本的p当作是前插的节点罢了
    //时间o(1)
    //给了头节点去从头找p的前插的话,时间o(n)
    return true;
}
bool ListDelete(LinkList& l, int i, int& e)//按位删除,带头结点,i表示第i个,e表示删除位置的data

{
    if (i < 1)
        return false;
    LNode* p=l;
    int j = 0;
    while (p != NULL && j < i - 1)
    {
        p = p->Next;
        j++;


    }
    if (p == NULL)
        return false;
    if (p->Next == NULL)
        return false;
    LNode* q = p->Next;
    p->Next = q->Next;
    e = q->data;
    free(q);
    return true;

    //时间o(n)
}
bool DeleteNode(LNode* p)//指定节点删除
{
    if (p == NULL)
        return false;
    LNode* q = p->Next;
    if (q == NULL)
    {
        cout << "此方法不可行,p已是最后节点,q此时会报错,此时应采用头节点找p前驱的法,o(n)";
        return false;

    }
    p->data = p->Next->data;
    p->Next = q->Next;
    free(q);
    return true;
    //仍是用后继节点代替p删除,从而达成删除p的效果,时间o(1)


}
bool DeleteNextDNode(DNode* p)//删除p的后续节点
{
    if (p == NULL)
        return false;
    DNode* q = p->Next;
    if (q == NULL)
        return false;
    p->Next = q->Next;
    if (q->Next != NULL)
        q->Next->prior = p;
    free(q);
    return true;


}
void DestoryList(DLinklist& l)
{
    while (l->Next != NULL)
    DeleteNextDNode(l);
    free(l);
    l = NULL;

}
LNode *GetElem(LinkList l,int i)//按位查找,与上述代码片段相同,o(n)
{
    if (i < 0)
        return NULL;
    LNode* p=l;
    int j = 0;
    while (p != NULL && j < i )
    {
        p = p->Next;
        j++;

    }
    return p;

}
LNode* LocalElem(LinkList l, int e)//按值查找,o(n)
{

    LNode* p = l->Next;
    while (p != NULL &&p->data!=e)
    {
        p = p->Next;

    }
    return p;

}
int Length(LinkList l)//统计链表长
{
    int len = 0;
    LNode* p = l;
    while (p->Next != NULL)
    {
        p = p->Next;
        len++;//时间  o(n)
    }
    return len;

}
//尾插法:1.可以不断调用ListInsert插入最后一位,但双重循环,时间上为o(n^2)
LinkList List_TailInsert(LinkList& L)//课本尾插法
{
    int x;
    L = (LinkList)malloc(sizeof(LNode));//头
    LNode* s, * r = L;
    cin >> x;
    while (x != 9999)//结束标志
    {
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        r->Next = s;
        r = s;
        cin >> x;

    }
    r->Next = NULL;
    return L;

}
LinkList nohead_List_TailInsert(LinkList& L)//无头尾插法
{
  
    LNode* s, * r=NULL;
    int x;
    cin >> x;
    while (x != 9999) {
        s = (LNode*)malloc(sizeof(LNode));
        s->data = x;
        s->Next = NULL;
        if (NULL == L) {
            L = s;//将新结点位置首节点也是尾结点
         
        }
        else {
            r->Next = s;
     
        }
        r = s;
        cin >> x;

    }
    r->Next = NULL;
    return L;

}
LinkList List_headInsert(LinkList& l)//头插,也就是后插 ,用于逆置
{
    LNode* s;
    int x;
    l = (LinkList)malloc(sizeof(LNode));//头
    l->Next = NULL;//此句为了清除脏数据
    cin >> x;
    while (x != 9999)
    {
        s = (LNode*)malloc(sizeof(LNode));//逆置链表的思想,建议实操
        s->data = x;//逆置链表的思想
        s->Next = l->Next;//逆置链表的思想
        l->Next = s;//逆置链表的思想
        cin >> x;
    }
    return l;
}
   
//页数43 p1-13
bool  p1(LinkList head, int e)
{
    while (head->Next!= NULL)
    {
        if (head->Next->data == e)
        {
            LNode* s = head->Next;
            if (s->Next == NULL)
            {
                free(s);
                return true;

            }
            head->Next = s->Next;
            free(s);
            continue;

        }
        head = head->Next;

    }
   
   
    return true;



}
bool p2(LinkList head)
{     int minnum = head->Next->data;
       LNode* prior=NULL; LNode* cur=NULL; 
       
     
    while (head->Next != NULL)
    {
       

        if (head->Next->data < minnum)
        {
            minnum =head->Next->data;
             prior = head;
             cur = head->Next;

        }
        head = head->Next;

    }
    if (prior != NULL && cur != NULL)
    {
        prior->Next = cur->Next;
        free(cur);
        return true;

    }
    

    return false;


}

LinkList p3(LinkList l)
{
    LNode* cur = l->Next;
    LNode* pn = NULL;
    l->Next = NULL;
    while (cur!=NULL)
    {   
        pn = cur->Next;
        cur->Next = l->Next;
        l->Next = cur;
        cur = pn;

     }
    return  l;



}


bool  p4(LinkList head, int n,int N)
{
    while (head->Next != NULL)
    {
        if (head->Next->data > n && head->Next->data < N)
        {
            LNode* s = head->Next;
            if (s->Next == NULL)
            {
                free(s);
                return true;

            }
            head->Next = s->Next;
            free(s);
            continue;

        }
        head = head->Next;

    }


    return true;



}
void p6(LinkList temp)//原题a,b的大小为n,故原链表元素必为偶数,此算法也仅是考虑了偶数。王道中是单节点更加简便,但时间复杂度都为o(n)
{
    LNode* prior = temp->Next;
    LNode* cur = prior->Next;
    temp->Next = NULL;
    if (prior == NULL || cur == NULL)
        return;
    LNode*a= (LinkList)malloc(sizeof(LNode));
    LNode*b = (LinkList)malloc(sizeof(LNode));
    LNode* tail = a;
    LNode* head = b;
    b->Next = NULL;
   while (prior&&cur )
    {
        tail->Next = prior;//weicha
        tail = prior;//weicha
        prior = cur->Next;

        cur->Next = head->Next;//toucha
        head->Next = cur;//toucha 
        if (!prior) break;
        cur = prior->Next;
      
       } 
    tail->Next = NULL;
    print(a);
    cout << endl;
    print(b);

}
void p7(LinkList temp)//前提为排序列表,记录当前值即可。

{
    LNode* prior = temp->Next;
    if (!prior)
     return;
    int num = prior->data;
    LNode* cur = prior->Next;
    if (cur == NULL)
    {
        cout << prior->data;
        return;

    }
    while (cur->Next!= NULL)
    {
        if (cur->data == num)
        {
            prior->Next = cur->Next;
            LNode* tmp = cur;
            cur = cur->Next;
            free(tmp);
            continue;

        }
        cur = cur->Next;
        prior = prior->Next;
        num = prior->data;
    }


    print(temp);
    cout << endl;


}
void p8(LinkList a, LinkList b)
{
    LNode* p = a->Next;
    LNode* q = b->Next;

    LNode*c = (LinkList)malloc(sizeof(LNode));
    LNode* r = c;
    while (p && q)
    {
        if (p->data < q->data)
        {
            p = p->Next;
        }
        else  if(p->data > q->data)  q = q->Next;
        else {
            LNode* s = (LinkList)malloc(sizeof(LNode));
            s->data = p->data;
            r->Next = s;
            r = s;
            p = p->Next;
            q = q->Next;



        }



    }

    r->Next = NULL;
    print(c);
    cout << endl;


}
LinkList p9(LinkList& a, LinkList& b)
{

    LNode* p = a->Next;
    LNode* q = b->Next;
    LNode* u, * pc = a;
    while (p && q)
    {
        if (p->data == q->data)
        {
            pc->Next = p;
            pc = p;
            p = p->Next;
            u = q;
            q = q->Next;
            free(u);


        }
        else if (p->data < q->data)
        {
            u = p;p = p->Next;
            free(u);



         }
        else {
            u = q;
            q = q->Next;
            free(u);

        }



    }

    while (p)
    {
        u = p;
        p = p->Next;
        free(u);



    }
    while (q)
    {

        u = q;
        q = q->Next;
        free(u);

    }
    pc->Next = NULL;
    free(q);
    return a;



}
bool p10(LinkList a, LinkList b)//kmp的雏形,这里偷懒直接暴力了,王道答案也是暴力
{   
    LNode* p = a->Next;
    LNode* q = b->Next;
    LNode* prior = p;
    while (p && q)
    {
        if (p->data == q->data)
        {
            p = p->Next;
            q = q->Next;


        }
        else {
            prior = prior->Next;
            p = prior;
            q = b->Next;


        }
        if (q==NULL)
            return  true;
        else
            return false;

    }

}
bool p11(DLinklist l)//从头指针开始一个向左一个向右,相等就继续不等就判假即可,样例就不给出了。
{
    DNode* p = l->Next;
    DNode* q= l->prior;
    while (p != q && q->Next != p)
    {
        if (p->data == q->data)
        {
            p = p->Next;
            q = q->Next;



        }
        else
            return false;


    }


    return true;



}
LinkList  p12(LinkList& a, LinkList& b)//a,b默认为循环单链表,循环链表的题很少用样例重在思想了。
{//一个选择题的思想,找到两个单循环表的尾巴相连再做一些细节处理
    LNode* p, * q;
    p = a;
    while (p->Next != NULL)
        p = p->Next;
    q = b;
    while (q->Next != NULL)
        q = q->Next;
    p->Next = b;
    q->Next = a;
    return a;



}
typedef struct DNode13 {//13题双链表,初始化里记得freq置零,此处不演示初始化也不加样例,读者自行实现即可

    int data;
    int freq=0;
    struct DNode13* Next;
    struct DNode13* prior;//前驱指针
}DNode13, * DLinklist13;
DLinklist13  p13(DLinklist13& l, int e)
{
    DLinklist13  p = l->Next;
    DLinklist13  q;//用来记录找的位置
    while (p && p->data != e)
        p = p->Next;
    if (!p)
    {
        cout << "ERROR";
        exit(-1);

    }
    else {
        p->freq++;
        if (p->prior == l || p->prior->freq > p->freq)
            return p;//p在首或者p比前面少,都说明现在的位置已经是要求的,直接返回
        if (p->Next)p->Next->prior = p->prior;
        p->prior->Next = p->Next;
        q = p->prior;
        while (q != l && q->prior->freq <= p->freq)//q从p的prior位置往前找,要么找到头要么找到第一个比他freq值大的地方,在其后面插入p;
            q = q->prior;
        p->Next = q->Next;
        p->prior = q;
        q->Next->prior = p;
        q->Next = p;



    }
    return p;




}
void p14(LinkList l, int k)//转换成循环单链表,找到尾节点后断开,注:l不含头节点
{
    LNode* p = l;
    int lenth=1;
    while (p->Next != NULL)
    {
        p = p->Next;
        lenth++;
    }
    p->Next = l;
    p = l;
    for (int i = 1;i < lenth - k;i++)
    {
        p = p->Next;

    }
    l = p->Next;
    p->Next = NULL;
    nohead_print(l);

}
LinkList p15(LinkList head)//Map映射法,或者答案的双指针法,但是环入口不好找,a=nr-x
{
    LinkList fast = head;
    LinkList slow = head;
    while (fast != NULL && fast->Next != NULL)
    {
        slow = slow->Next;
        fast = fast->Next->Next;
        if (slow == fast)
            break;

    }
    if( fast->Next == NULL||fast == NULL )
     return NULL;
    LinkList ph = head;
    LinkList ps = slow;
    while (ph != ps)
    {
        ph = ph->Next;
        ps = ps->Next;

    }//a=nr-x
    return ph;

}
int p16(LinkList head)//注:无头指针的链表
{
    LNode* fast = head->Next;
    LNode* slow = head;
    while (fast->Next != NULL && fast != NULL)
    {
        slow = slow->Next;
        fast = fast->Next->Next;
    }
    LNode* s = slow->Next;
    LNode* tmp;
    LNode* newhead = (LinkList)malloc(sizeof(LNode));//我带了头节点,带不带都行
    newhead->Next = NULL;
    while (s)
    {
        tmp = s->Next;
        s->Next = newhead->Next;
        newhead->Next = s;
        s = tmp;
    }
    int max = 0;
    LNode* first = head;
    LNode* second = newhead->Next;
    while (first &&second)
    {
        if ((first->data + second->data) > max)
            max = first->data + second->data;
        first = first->Next;
        second = second->Next;


    }
    return max;


}
int p17(LinkList head,int k)
{
    LinkList p = head;
    LinkList q = head;
    int count = 0;
    while (p)
    {
        if (count < k)
        {
            count++;
            p = p->Next;
        }
        else
        {
            q = q->Next;
            p = p->Next;

        }


    }
    if (count < k)
        return 0;
    else {
        cout << q->data;
        return 1;
    }







}
LinkList p18(LinkList str1, LinkList str2)//第五题的具体实现,不再详解
{
    int m = Length(str1);
    int n = Length(str2);
    LinkList p, q;
    for (p = str1;m > n;m--)
        p = p->Next;
    for (q = str2;m < n;n--)
        q = q->Next;
    while (p->Next != NULL && p->Next != q->Next)
    {
        p = p->Next;
        q = q->Next;
    }
    return p->Next;
}

void p19(LinkList head, int n)
{
    LinkList p = head;
    LinkList r;
    int* q, m;
    q = (int*)malloc(sizeof(int) * (n + 1));
    for (int i = 0;i < n + 1;i++)
        *(q + i) = 0;
    while (p->Next != NULL)
    {
        m = abs(p->Next->data);
        if (*(q + m) == 0)
        {
            *(q + m)=1;
            p = p->Next;

        }
        else
        {
            r = p->Next;
            p->Next = r->Next;
            free(r);




        }




    }

    free(q);

}
void p20(LinkList head)
{
    LNode* fast = head->Next;
    LNode* slow = head;
    while (fast->Next != NULL && fast != NULL)
    {
        slow = slow->Next;
        fast = fast->Next->Next;
    }
    fast = slow->Next;
    slow->Next = NULL;
    LinkList tmp;
    while (fast)
    {
        tmp = fast->Next;
        fast->Next = slow->Next;
        slow->Next = fast;
        fast = tmp;

    }
    LinkList s;
    LinkList r;
    s = head->Next;
    fast = slow->Next;
    while (fast)
    {
        r = fast->Next;
        fast->Next = s->Next;
        s->Next = fast;
        s = fast->Next;
        fast = r;

    }
}
int main()
{  /*  p1
    LNode* L;
    List_TailInsert(L);
    print(L);
    cout << endl;
    if (p1(L,5))  
    print(L);*/

    //p2
    //LNode* L;
    //List_TailInsert(L);
    //print(L);
    //cout << endl;
    //if (p2(L))//o(n)
    //print(L);




    //p3
  /*  LNode* L;
    List_TailInsert(L);
    print(L);
    cout << endl;
    L = p3(L);
    print(L);*/
  

   // p4
  /* LNode* L;
   List_TailInsert(L);
   print(L);
   cout << endl;
   if (p4(L,2,5))
   print(L);*/



  /*  p5
  * 找到两个链表的公共节点,找到两个链表的头节点p,q,同时如果有公共节点就意为着这两个链表最后是Y型,最后尾节点处p=q找到
  * 那么可以考虑两个链表同步遍历直到满足p=q
  *两个链表长度可能不同,分别遍历得到两个长度,len1,len2(假设1》2),算出长度差,长的先遍历(len1-len2),然后同步遍历直到p=q;
  
  */



    //LNode* L;
    //List_TailInsert(L);
    //print(L);
    //cout << endl;
    //p6(L);



  /*  LNode* L;
    List_TailInsert(L);
    print(L);
    cout << endl;
    p7(L);*/
  
    //LNode* La;
    //LNode* Lb;
    //List_TailInsert(La);
    //List_TailInsert(Lb);
    //print(La);cout << endl;
    //print(Lb);cout << endl;
    //p8(La, Lb);

    //LNode* La;
    //LNode* Lb;
    //List_TailInsert(La);
    //List_TailInsert(Lb);
    //print(La);cout << endl;
    //print(Lb);cout << endl;
    //La=p9(La, Lb);
    //print(La);


    // LNode* La;
    //LNode* Lb;
    //List_TailInsert(La);
    //List_TailInsert(Lb);
    //print(La);cout << endl;
    //print(Lb);cout << endl;
    //if (p10(La, Lb))
    // cout << "是的";
    //else cout << "NO";

  /*  LNode* L = NULL;
    int k;
    cin >> k;
    nohead_List_TailInsert(L);
   nohead_print(L);
    cout << endl;
    p14(L,k);*/

    //LNode* L = NULL;
    //nohead_List_TailInsert(L);
    //nohead_print(L);
    //cout << endl;
    //cout << p16(L);



}

所用样例

1 2 2 3 4 8 9999   //1
5 9 9 5 4 3 9999   //1
8 9 9 5 5 6 4 2 2 2 1 9999//2
1 2 3 4 5 6 7 8 9999//3
1 2 2 3 4 8 9999   //4
5 9 9 5 4 3 9999   //4
1 2 2 3 4 8 9999   //6
5 9 9 5 4 3 9999   //6
1 2 2 3 4 8 9999   //7
7 10 10 21 30 42 42 42 51 70 9999//7
1 2 3 4 5 6 7 8 9999//8
4 5 6 7 8 9 9999//8
1 2 3 4 5 6 7 8 9999 //9
4 5 6 7 8 9 9999       //9
8 9 9 5 5 6 4 2 2 2 1 9999//10
5 5 6 4 9999 //10

8 9 9 5 5 6 4 2 2 2 1 9999//10
9 5 6 4 9999//10
1
0 1 2 3 9999      //14
8 9 9 5 5 6 4 2 5 2 9999//16  result=14

注:

样例相对简单,有错误恳请各位大佬批评指正!

图中警告可以采取

#pragma warning(disable:28182)

注释掉

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值