线性表之链表复习(仅王道单链表题目)

考研408复习,如发现任何错误,请私聊,不胜感谢

单链表代码已更新完毕。

如下:

#include <iostream>
#include <algorithm>
#include <string>
#include <cmath>
#include <iomanip>
#include <cstring>

using namespace std;

typedef struct LNode
{
    int data;
    LNode *next;
}Lnode, *Linklist;
///逆序建立链表
Linklist CreatepositiveLinklist(Linklist &head, int n)
{
    head = new Lnode;
    head->next = NULL;
    for(int i=0;i<n;++i)
    {
        Linklist p = new Lnode;
        cin>>p->data;
        p->next = head->next;
        head->next = p;
    }
    return head;
}
///正序建立链表
Linklist CreateNegativeLinklist(Linklist &head, int n)
{
    Linklist tail;
    head = new Lnode;
    head->next = NULL;
    tail = head;
    for(int i=0;i<n;++i)
    {
        Linklist p = new Lnode;
        cin>>p->data;
        p->next = NULL;
        tail->next = p;
        tail = p;
    }
    return head;
}
///打印链表
void print_Linklist(Linklist head)
{
    if(head->next == NULL)
    {
        cout<<"The Linklist is NULL !"<<endl;
        return;
    }
    while(head->next->next)
    {
        cout<<head->next->data<<" ";
        head = head->next;
    }
    cout<<head->next->data<<endl;
}
///按下标查找结点
Lnode *Find_Lnode_byid(Linklist head, int key)
{
    if(key == 0)
        return head;
    if(key < 1)
        return NULL;
    int num = 1;
    head = head->next;
    while(head && num < key)
    {
        head = head->next;
        num++;
    }
    return head;
}
///在position处插入节点值为key的元素
void Insert_Lnode(Linklist &head, int position, int key)
{
    if(position <= 0)
    {
        cout<<"输入不合法,插入失败!"<<endl;
        return;
    }
    Linklist p = Find_Lnode_byid(head, position-1);
    Linklist temp = new Lnode;
    temp->data = key;
    temp->next = p->next;
    p->next = temp;
}
///删除位置为position的节点
void Delete_Lnode(Linklist &head, int position)
{
    if(position <= 0)
    {
        cout<<"The input is ERROR!, delete failed!"<<endl;
        return;
    }
    Linklist p = Find_Lnode_byid(head, position);
    Linklist q = p->next;
    p->next = q->next;
}
///求链表长度
int Linklist_length(Linklist head)
{
    if(head->next == NULL)
        return 0;
    int num = 0;
    while(head->next)
    {
        num++;
        head = head->next;
    }
    return num;
}

///以下为一些综合应用分析题,具有详细题目描述
///1.设计一个递归算法,删除不带头节点的单链表L中所有值为x的节点。
void The_first_problem(Linklist &head, int key)
{
    if(head == NULL)
        return;
    if(head->data == key)
    {
        Linklist p = head;
        head = head->next;
        free(p);
        The_first_problem(head, key);
    }
    else
        The_first_problem(head->next, key);
}
///这里做一个理解说明:函数进行递归调用时,只是将head进行next操作,并没有改变被删除节点的前驱结点的next指向,疑似断链操作
///其实不然,这里head为调用该函数的外层head->next,故这里实现了head->next=head-next->next的造作过程。
///2.在带头节点的单链表L中,删除所有值为x的节点,并释放其空间,假设值为x的节点不唯一。
Linklist The_second_problem(Linklist &head, int x)
{
    Linklist q = head;
    Linklist p = head->next;
    while(p)
    {
        if(p->data == x)
        {
            q->next = p->next;
            free(p);
            p=q->next;
        }
        else
        {
            p=p->next;
            q=q->next;
        }
    }
    return head;
}

///3.设L为带头节点的单链表,编写算法实现从尾到头反向输出每个节点的值
void The_third_problem1(Linklist head)///利用辅助空间解决问题
{
    int *temp = new int[Linklist_length(head)];
    Linklist p = head->next;
    for(int i=0;i<Linklist_length(head); ++i, p=p->next)
    {
        temp[i] = p->data;
    }
    for(int i=Linklist_length(head)-1; i>0; --i)
        cout<<temp[i]<<" ";
    cout<<temp[0]<<endl;
}

void The_third_problem2(Linklist head)///使用递归思想解决问题
{
    if(head->next)
        The_third_problem2(head->next);
    cout<<head->data<<" ";
}

///4.试编写在带头节点的单链表L中删除一个最小值节点的高效算法(假设最小值节点是唯一的)
Linklist The_four_problem(Linklist &head)
{
    ///保存最小值节点的位置及其前驱位置
    Linklist q = head, p=head->next;
    Linklist mixn = p, mixnpre = q;
    while(p)
    {
        if(p->data < mixn->data)
        {
            mixn = p;
            mixnpre = q;
        }
        p = p->next;
        q = q->next;
    }
    mixnpre->next = mixn->next;
    free(mixn);
    return head;
}
///5.试编写算法将带头结点的单链表就地逆置,所谓就地是指辅助空间复杂度为O(1)
Linklist The_five_problem1(Linklist &head)
{
    Linklist p = head->next;
    Linklist q = p->next;
    head->next = NULL;
    while(p)
    {
        p->next = head->next;
        head->next = p;
        p = q;
        if(q)
            q = q->next;
    }
    return head;
}

Linklist The_five_problem2(Linklist &head)
{
    Linklist pre, p=head->next, r=p->next;
    p->next = NULL;
    while(r)
    {
        pre = p;
        p = r;
        r = r->next;
        p->next = pre;
    }
    head->next = p;
    return head;
}
///6.有一个带头节点的单链表L,设计一个算法,使其元素递增有序
///愿你阅尽千帆,归来仍是少年
Linklist The_six_problem(Linklist &head)
{
    ///采用插入排序思想,即构造一个单链表,然后遍历L,每走一个节点,插入一个节点。
    Linklist p = head->next, r = p->next;
    p->next = NULL;
    p = r;
    r = r->next;
    while(p)
    {
        Linklist temp = head->next, tempre = head;
        while(tempre)
        {
            if(temp == NULL)
            {
                tempre->next = p;
                p->next = NULL;
                break;
            }
            if(p->data < temp->data)
            {
                p->next = temp;
                tempre->next = p;
                break;
            }
            temp = temp->next;
            tempre = tempre->next;
        }
        if(r)
        {
            p = r;
            r = r->next;
        }
        else
            break;
    }
    return head;
}
///7.设在一个带表头节点的单链表L中所有元素节点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值之间的元素
///人生一棋局,无法跳脱,终究是棋子。
Linklist The_seven_problem(Linklist &head, int a, int b)
{
    Linklist p = head->next;
    Linklist q = head;
    while(p)
    {
        if(p->data >= a && p->data <= b)
        {
            q->next = p->next;
            free(p);
            p = q->next;
        }
        else
        {
            p = p->next;
            q = q->next;
        }
    }
    return head;
}

///8.给定两个单链表,编写算法找出两个链表的公共节点
///虚无缥缈者,是否虚幻。
Linklist The_eight_problem(Linklist head1, Linklist head2)
{
    ///明确公共节点的定义,即如果两个链表拥有公共节点,那么在该节点之后的所有节点都是重合的,即他们最后一个节点必然是重合的。
    int len1 = Linklist_length(head1), len2 = Linklist_length(head2);
    Linklist longlist, shortlist;
    int dist = abs(len1-len2);///两表长之差
    if(len1 > len2)
    {
        longlist = head1->next;
        shortlist = head2->next;
    }
    else
    {
        longlist = head2->next;
        shortlist = head1->next;
    }
    while(dist--)
    {
        longlist = longlist->next;
    }
    while(longlist)
    {
        if(longlist == shortlist)
            return longlist;
        longlist = longlist ->next;
        shortlist = shortlist ->next;
    }
    return NULL;
}
///9.给定一个带头节点的单链表,按照递增次序输出单链表中各节点的数据元素,并释放节点所占的存储空间。(不允许使用数组做辅助空间)
///向来历史都是由强者书写
Linklist The_nine_problem(Linklist &head)
{
    ///嵌套双重循环,遍历一次找到最小值输出并释放节点空间
    while(head->next)
    {
        Linklist p = head->next;
        Linklist pre = head;
        Linklist mixn = p, mixnpre = pre;
        while(p)
        {
            if(p->data < mixn->data)
            {
                mixn = p;
                mixnpre = pre;
            }
            else
            {
                p = p->next;
                pre = pre->next;
            }
        }
        cout<<mixn->data<<endl;
        mixnpre->next = mixn->next;
        free(mixn);
    }
    return head;
}

///10.将一个带头节点的单链表A分解为两个带头结点的单链表的A和B,是的A表中元素为原表奇数序号的元素,B表中元素为原表偶数序号的元素,且保持其相对顺序不变。
///逆风翻盘,向阳而生
void The_ten_problem(Linklist &head, Linklist &head1, Linklist &head2)
{
    Linklist tail2;
    head2 = new Lnode;
    head2->next = NULL;
    tail2 = head2;
    Linklist tail1;
    head1 = new Lnode;
    head1->next = NULL;
    tail1 = head1;
    Linklist p = head->next;
    int len = Linklist_length(head);
    for(int i=1;i<=len;i++)
    {
        if(i%2)
        {
            tail1->next=p;
            tail1 = p;
        }
        else
        {
            tail2->next = p;
            tail2 = p;
        }
        p = p->next;
    }
    tail1->next = NULL;
    tail2->next = NULL;
}
///11.设C={a1, b1, a2, b2,......an, bn}为线性表,采用带头节点的单链表存放,设计一个就地算法,使A={a1, a2, ...an},B={bn, ...b2, b1}
///与上题思路相同,只不过B单链表改成尾插法。
///12.在一个递增有序的线性表中,有数值相同的元素存在,存储方式为单链表,设计算法去掉数值相同的元素,是表中不存在相同元素。
Linklist The_twelve_problem(Linklist &head)
{
    Linklist p = head->next;
    Linklist q = p->next;
    while(q)
    {
        if(p->data==q->data)
        {
            while(p->data == q->data)
            {
                if(q->next)
                    q = q->next;
                else
                    break;
            }
            if(q->next)
                p->next = q;
            else
                p->next = q->next;
        }
        p=p->next;
        q=q->next;
    }
    return head;
}
///13.假设有两个按元素值递增次序排列的线性表,均以单链表形式存储,归并为一个按照元素值递减的=次序排列的单链表
///并要求利用原来两个单链表节点存放归并后的单链表
Linklist The_thirteen_problem(Linklist &head1, Linklist &head2)
{
    ///从小开始比较,采用逆序建链表方法
    Linklist p = head1->next;
    Linklist q = head2->next;
    Linklist r;
    head1->next = NULL;
    while(p && q)
    {
        if(p->data < q->data)
        {
            r = p->next;
            p->next = head1->next;
            head1->next = p;
            p = r;
        }
        else
        {
            r = q->next;
            q->next = head1->next;
            head1->next = q;
            q = r;
        }
    }
    if(p)
    {
        q = p;
    }
    while(q)
    {
        r = q->next;
        q->next = head1->next;
        head1->next = q;
        q = r;
    }
    free(head2);
    return head1;
}
///14.设A和B是两个单链表(带头节点), 其中元素递增有序,设计一个算法从A和B中公共元素产生单链表C,要求不破坏A和B的节点
Linklist The_fourteen_problem(Linklist &head1, Linklist &head2)
{
    Linklist head = new Lnode;
    head->next = NULL;
    Linklist p = head1->next;
    Linklist q = head2->next;
    Linklist r = head;
    while(p && q)
    {
        if(p->data <q->data)
            p=p->next;
        else if(p->data > q->data)
            q = q->next;
        else
        {
            Linklist s;
            s = new Lnode;
            s->data = p->data;
            s->next = NULL;
            r->next = s;
            r = s;
            p=p->next;
            q=q->next;
        }
    }
    return head;
}
///15.已知两个链表A和B分别表示两个集合,其元素递增排列。编制函数,求A和B的交集,并存放于A链表之中
Linklist The_fifteen_problem(Linklist &head1, Linklist &head2)
{
    ///较为简单的归并算法,给出王道算法
    Linklist p = head1->next;
    Linklist q = head2->next;
    Linklist c = head1, u;
    while(p && q)
    {
        if(p->data == q->data)
        {
            c ->next = p;
            c=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);
    }
    c->next=NULL;
    free(head2);
    return head1;
}
///16.两个连续子序列,判断b是否为a的连续子序列
bool The_sixteen_problem(Linklist &head1, Linklist &head2)
{
    Linklist p = head1->next;
    Linklist q = head2->next;
    Linklist pre = p;
    while(p && q)
    {
        if(q->data == p->data)
        {
            q = q->next;
            p = p->next;
        }
        else
        {
            pre = pre->next;
            p = pre;
            q = head2->next;
        }
    }
    if(q == NULL)
        return true;
    return false;
}
///21.单链表,查找链表中倒数第k个位置上的节点,若查找成功,输出数据并返回1,否则只返回0
bool The_twentyone_problem(Linklist head, int k)
{
    ///算法思想,p,q同时指向第一个元素,p先开始移动,当p移动到第k个元素时,q之后与p同步向后移动
    ///这样当p移动到最后一个元素时,q移动到倒数第k个元素
    Linklist p = head->next;
    Linklist q = p;
    int num = 1;
    while(p)
    {
        if(num <= k)
        {
            cout<<"xunhuan "<<p->data<<endl;
            p=p->next;
            num++;
            continue;
        }
        cout<<"p: "<<p->data<<endl;
        p = p->next;
        q = q->next;
    }
    if(num <= k)
        return 0;
    cout<<q->data<<endl;
    return 1;
}
///22.单链表,找出两个链表共同后缀的起始位置。说明时间复杂度。
///与第8题相仿,不予赘述
///23.单链表,删除绝对值相等的节点,仅保留第一次出现的节点。
Linklist The_twentythree_problem(Linklist &head, int n)
{
    int *temp = new int[n+1];
    Linklist p=head->next, pre = head;
    memset(temp, 0, n+1);
    while(p)
    {
        int data = p->data>0?p->data:-p->data;
        if(temp[data] == 0)
        {
            p=p->next;
            pre = pre->next;
            temp[data] = 1;
        }
        else
        {
            pre->next = p->next;
            free(p);
            p = pre->next;
        }
    }
    return head;
}
int main()
{
    ios::sync_with_stdio(false);
    Linklist head;
    int n;
    cin>>n;
    head = CreateNegativeLinklist(head, n);
    /*
    Linklist head1, head2;
    int n, m;
    cin>>n>>m;
    head1 = CreateNegativeLinklist(head1, n);
    head2 = CreateNegativeLinklist(head2, m);
    print_Linklist(head);
    cout<<Find_Lnode_byid(head, 3)->data<<endl;
    Insert_Lnode(head, 1, 999);
    print_Linklist(head);
    cout<<Linklist_length(head)<<endl;
    //The_first_problem(head, 5);
    //print_Linklist(head);
    //cout<<Linklist_length(head)<<endl;
    The_second_problem(head, 5);
    print_Linklist(head);
    cout<<Linklist_length(head)<<endl;
    The_third_problem1(head);
    The_third_problem2(head->next);
    head = The_four_problem(head);
    print_Linklist(head);
    head = The_five_problem2(head);
    print_Linklist(head);
    head = The_seven_problem(head, 2, 5);
    The_ten_problem(head, head1, head2);
    print_Linklist(head1);
    print_Linklist(head2);
    head = The_twelve_problem(head);
    print_Linklist(head);
    bool flag = The_sixteen_problem(head1, head2);
    cout<<flag<<endl;
    bool flag = The_twentyone_problem(head, 3);
    cout<<flag<<endl;*/
    head = The_twentythree_problem(head, 20);
    print_Linklist(head);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/AcSuccess/article/details/81435530