《面向对象的程序设计》OJC++单链表的学习

1.单链表的创建(结构体+链表)(查找数值)

题目描述

1.问题描述

给出初始数据,实现单链表的定义、创建、输出。

2.算法

单链表结点的存储结构包含两部分:数据、下一结点指针。

单链表的创建:输入n个数据e,若数据e不在单链表中,为数据e分配结点,并插入在单链表的尾部;若单链表中已有数据e,则不做任何操作。

单链表的输出:从头至尾遍历单链表,输出每个结点的元素值。

注:程序不可定义任何数组,否则不计成绩。

要求:查找定义子函数:int Find(Node *H,int e) //找到e返回1,找不到返回0。其中Node为链表结点结构体名,H为链表头指针。

输入

第一行:测试次数t

对每组测试数据,格式如下:

数据个数n 数据1 数据2 数据3 ... 数据n

输出

对每组测试数据,输出链表中元素个数和单链表中的全部数据。

输入样例

2

5 2 3 5 7 3

6 1 2 10 0 1 5

输出样例

4 2 3 5 7

5 1 2 10 0 5

AC代码

#include<iostream>
using namespace std;
struct node
{
    int num;
    node* next;
};
//在链表中查找某个元素
int find(node* h, int x)
{
    while (h->next != NULL)//当h不是最后一个且h不是空指针
    {
        h = h->next;//若h为头,h赋值为头后面的首个;若h为倒数第二个,h赋值为最后一个
        if (h->num == x)
            return 1;
    }
    return 0;
}
//创建链表同时不出现重复元素
void create(node* h, int& n)//直接引用n,对n进行修改
{
    h->next = NULL;
    //头指针指向下一个一定要赋值为NULL,防止野指针的出现
    node* pp = h, * p2;
    int x;
    int len = 0;//统计重复的数字
    for (int i = 0; i < n; i++)//n次输入
    {
        cin >> x;
        if (find(h, x) == 0)
        {
            p2 = new node;
            p2->next = NULL;
            //对临时变量p2赋值,p2也为末尾指针
            p2->num = x;
            pp->next = p2;
            pp = p2;
            //pp移动到末尾来进行下次添加元素
        }
        else
            len++;//重复元素
    }
    n = n - len;//最后所剩元素个数
}
int main()
{
    int t, n;
    cin >> t;
    while (t--)
    {
        node* h = new node;
        cin >> n;
        create(h, n);
        cout << n << " ";
        //链表输出
        while (h->next != NULL)
        {
            h = h->next;
            //此步要先进行,因为h->num里面没有输入的值
            cout << h->num << " ";
        }
        cout << endl;
    }
    return 0;
}

2.链表的逆序输出(链表)

题目描述

按数字输入顺序创建单链表。不可借助数组、容器,不可改变原链表、不可开辟新结点空间。编程实现单链表的逆序输出。

输入

测试次数t

每组测试数据一行,格式如下:

数据个数n,后跟n个整数

输出

对每组测试数据,逆序输出单链表。

输入样例

2

10 1 2 3 4 5 6 7 8 9 10

4 19 20 15 -10

输出样例

10 9 8 7 6 5 4 3 2 1

-10 15 20 19

AC代码

#include<iostream>
using namespace std;
struct node
{
    int num;
    node* next;
};
void create(node* h, int n)
{
    h->next = NULL;
    int x;
    node* pp = h, * p2;
    for (int i = 0; i < n; i++)
    {
        cin >> x;
        p2 = new node;
        p2->next = NULL;
        p2->num = x;
        pp->next = p2;
        pp = p2;
    }
    pp->next = NULL;
}
//逆序输出链表采用递归的方法
void reverse(node* h)
{
    if (h->next == NULL)//如果到链表的最后一个
    {
        cout << h->num << " ";
        return;//一定要记得return
    }
    else if (h->next)reverse(h->next);
    //先进行reverse后再输出(也就是先去到尾部再往前一个一个输出)
    cout << h->num << " ";
    return;
    //这里同样要return;
    //因为已经输出一个数要返回到上一个节点继续输出
}
int main()
{
    int t,n;
    cin >> t;
    while (t--)
    {
        cin >> n;
        node* h = new node;
        create(h, n);
        reverse(h);
        cout << endl;
    }
    return 0;
}

3.单链表的查找(查找下标)(结构体+链表)

题目描述

1.问题描述

给出初始数据,实现单链表的定义、创建、查找。假设单链表中的结点计数从1开始。

2.算法

单链表结点的存储结构包含两部分:数据、下一结点指针。

单链表的创建:依次为输入的数据分配结点,并按序链接起来。

单链表结点个数L(也称单链表表长L):从头至尾遍历单链表,对结点进行计数。

单链表的查找:给出位置i,若第i个结点存在(1<=i<=L),返回结点地址;否则,返回NULL。

要求查找子函数定义为:Node *Find(Node *H,int i)

//若i的值在1...单链表长L之间,返回第i个结点的地址;否则返回空指针NULL。其中Node为链表结点结构体名,H为链表头指针。

输入

每个样本分2行:

第一行:第一个数字n表示样本数目,其后跟n个样本。

第二行:查找测试次数m 后跟m个待查找的位置。

输出

第一行:单链表创建后,输出链表中元素个数和单链表中的全部数据。

第二行到第n+1行,对每个查找位置,若结点存在,输出结点数据;否则输出error。

输入样例

6 1 2 3 4 5 8

4 0 2 10 6

输出样例

6 1 2 3 4 5 8

error

2

error

8

AC代码

#include<iostream>
using namespace std;
struct node
{
    int num;
    node* next;
};
void create(node* h, int n)
{
    h->next = NULL;
    int x;
    node* pp = h, * p2;
    for (int i = 0; i < n; i++)
    {
        cin >> x;
        p2 = new node;
        p2->next = NULL;
        p2->num = x;
        pp->next = p2;
        pp = p2;
    }
}
node* find(node* h, int x)//返回一个结点node*型,注意x为下标
{
    if (x <= 0)return NULL;
    //特判,因为x从1开始
    node* p = h;
    int j = 1;
    while (p != NULL && j <= x)//不用p->next!=NULL是因为p可以为最后一个,注意j能为x,注意p才会是第x个结点
    {
        p = p->next;//j==1时p为链表的首元素
        j++;
    }
    return p;
    //返回结点
}
int main()
{
    int n;
    cin >> n;
    node* h = new node;
    create(h, n);
    //输出链表
    cout << n << " ";
    node* p = h;//保留h不变
    while (p->next != NULL)
    {
        p = p->next;
        cout << p->num << " ";
    }
    cout << endl;
    //开始询问
    int q;
    cin >> q;
    while (q--)
    {
        int x;
        cin >> x;
        if (find(h, x) != NULL)cout << find(h, x)->num << endl;
        else cout << "error" << endl;
    }
    return 0;
}

4.单链表的插入(指定某位置插入某元素)(结构体+链表)

题目描述

1.问题描述

单链表初始为空,给定插入位置和数据,插入结点实现单链表的创建。假设单链表中的结点计数从1开始。

2.算法

单链表结点的存储结构包含两部分:数据、下一结点指针

单链表的查找:给出位置i,若第i个结点存在(1<=i<=表中结点数L),返回结点地址;否则,返回NULL。

单链表的插入:给出位置i和数据e,在单链表第i(1<=i<=L+1)个结点位置插入新结点,数据为e。

输入

测试次数n

每行一组测试数据,格式如下:

位置i 数据e

输出

对每组测试数据,调用插入函数在位置i插入数据e,若插入成功,输出当前链表中的数据;若插入不成功,输出error。

输入样例

8

0 10

1 10

2 20

3 30

1 40

6 60

5 50

9 100

输出样例

error

10

10 20

10 20 30

40 10 20 30

error

40 10 20 30 50

error

AC代码

#include<iostream>
using namespace std;
struct node
{
    int num;
    node* next;
};
bool insert(node* h, int idx, int val)//返回能否插入成功
{
    if (idx<1 || idx>h->num)//若下标不满足条件,无法插入
        return false;
    node* p = new node;
    node* q = h;
    p->num = val;
    //先找到idx-1的位置
    for (int i = 1; i < idx; i++)
    {
        q = q->next;
    }
    p->next = q->next;//这条语句一定要在前面
    q->next = p;
    h->num++;
    //h->num表示可插入的最大坐标!!(那一位是无元素的)
    return true;
}
int main()
{
    int n;
    cin >> n;
    node* h = new node;
    h->next = NULL;
    //头指针要初始好
    h->num = 1;//要初始为1,因为当idx==1时,可以插入,且h->num表示可插入的最大坐标!!
    while (n--)
    {
        int i, e;
        cin >> i >> e;
        int d = insert(h, i, e);
        //插入成功后h已经改变了
        node* p = h;
        if (d == 0)
            cout << "error" << endl;
        else
        {
            //注意这里输出与前面不太一样
            //最后一个元素后面直接换行没有空格
            //这也是为什么要用h->num储存元素个数的原因
            for (int i = 1; i <= h->num; i++)
            {
                if (p->next != NULL)//不能为最后一位,因为最后一位没有元素
                {
                    p = p->next;
                    cout << p->num;
                    if (i != h->num-1)//不是最后一个元素时,输出空格
                    {
                        cout << " ";
                    }
                }
            }
            cout << endl;
        }
    }
    return 0;
}

5.单链表的删除(结构体+链表)

题目描述

1.问题描述

给出初始数据,实现单链表的定义、创建、查找和删除。假设单链表中的结点计数从1开始。

2.算法

单链表结点的存储结构包含两部分:数据、下一结点指针。

单链表的创建:依次为输入的数据分配结点,并按序链接起来。

单链表的查找:给出位置i,若第i个结点存在(1<=i<=表中结点数L),返回结点地址;否则,返回NULL。

单链表的删除:给出位置i,删除第i个结点(1<=i<=L)。

要求定义删除函数:int DeleteList(Node *H,int i) //删除第i个结点成功,返回1;第i个结点不存在,删除不成功,返回0。其中Node是链表结点结构体名,H是链表头指针。

输入

每个样本分2行:

第一行:第一个数字n表示样本数目,其后跟n个样本

第二行:删除测试次数m 后跟m个删除位置

输出

第一行:单链表创建后,输出链表中元素个数和单链表中的全部数据。

第二行至第m+1行:若删除指定位置的数据成功,输出链表中元素个数和单链表中的全部数据;若删除不成功,输出error。

输入样例

5 2 4 3 5 7

3 0 2 4

输出样例

5 2 4 3 5 7

error

4 2 3 5 7

3 2 3 5

AC代码

#include<iostream>
using namespace std;
struct node
{
    int num;
    node* next;
};
void create(node* h, int n)
{
    h->next = NULL;
    node* pp = h, * p2;
    int x;
    for (int i = 0; i < n; i++)
    {
        cin >> x;
        p2 = new node;
        p2->next = NULL;
        p2->num = x;
        pp->next = p2;
        pp = p2;
    }
}
bool ddelete(node* h, int dix,int &n)//返回能不能删除成功
{
    if (dix<1 || dix>n)
        return 0;
    n--;
    node* pre = h;//为p的前一个结点
    node* p = h->next;//初始为链表首元素
    int count = 1;//统计下标(p的结点下标)
    while (p != NULL)
    {
        if (count == dix)
        {
            pre->next = p->next;
            //delete(p);
            p = NULL;
            return true;
        }
        count++;
        pre = pre->next;
        p = p->next;
    }
    return false;
}
//这里要多次输出链表使用函数方便
void show(node* h,int n)
{
    cout << n;
    node* p = h;
    while (p->next != NULL)
    {
        p = p->next;
        cout << " " << p->num;
        //这样最后一个不会输出空格(前提是要输出总数)
    }
    cout << endl;
}
int main()
{
    int q, n;
    cin >> n;
    node* h = new node;
    create(h, n);
    show(h,n);
    cin >> q;
    while (q--)
    {
        int x;
        cin >> x;
        if (ddelete(h, x, n))
            show(h, n);
        else
            cout << "error" << endl;
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值