数据结构 实验报告3

带头结点的单链表

代码有点长,但能保证,逻辑没有基本错误,程序能正确运行。(现在真的觉得链表很简单,加油,你也可以)

  1. 实验目的(结出本次实验所涉及并要求掌握的知识点)
  1. 理解带头结点的单链表的特点,掌握采用这种结构的算法设计。
  2. 熟练掌握运用带头结点的链表表示特定形式的数据的算法,并设计出有关算法.

2.实验内容(结出实验内容具体描述)

已知带头结点的单链表的存储结构定义同实验2,修改slnklish.h头文件中头插法、尾插法建表函数及链表输出函数,使其能正确应用于带头结点的单链表,在此基础完成实验1到实验9.

  1. 已知线性表存储在头结点的单链表的head中,请设计函数sort(linklist head),将head中的结点值按升序排序
  2. 已知两个带头结点的单链表l1,l2的结点值已按升序排序,设计函数linklist mergeascend(linklist l1,linklist l2)将l1,l2,合并为一个升序链表;设计函数linklist mergedescend(linklist l1,linklist l2),合并成一个降序链表。
  3. 设计算法函数linklist intersection(linklist l1,linklist l2),求两个单链表的交集。
  4. 编写函数void partion(linklist head),将带头结点的单链表head中奇数调整到前面,偶数调整到链表后面。
  5. 编写一个程序,,用尽可能快的方法返回带头结点中单链表中倒数第k个结点的地址如果不存在,则返回NULL。

3.算法描述及实验步骤(用适当的形式表达算法设计思想与算法实现步骤)

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef int datatype;
typedef struct node
{
    datatype data;
    struct node *next;
} node;
typedef node *linklist;
node *init()
{
    node *head;
    head = (node *)malloc(sizeof(node));
    head->next = NULL;
    return head;
}

void output(node *head)
{
    node *s;
    s = head->next;
    int i = 0;
    if (!s)
    {
        cout << "空的";
        return;
    }
    cout << "链表为:";
    while (s)
    {
        cout << s->data << ' ';
        i++;
        if (i % 10 == 0)
            cout << endl;
        s = s->next;
    }
    cout << endl;
}

node *createbyqueue()
{
    node *head = init();
    node *p = head;
    datatype x;
    cout << "请输入若干数据,以0位结束符:";
    cin >> x;
    while (x)
    {
        node *temp = (node *)malloc(sizeof(node));
        temp->data = x;
        p->next = temp;
        p = temp;
        cin >> x;
    }
    if (p)
        p->next = NULL;
    return head;
}

node *createbystack()
{
    node *head = init();
    node *p = head;
    node *s;
    datatype x;
    cout << "请输入若干数据,以0为结束符" << endl;
    cin >> x;
    while (x)
    {
        s = new node;
        s->data = x;
        if (head->next == NULL)
        {
            head->next = s;
            s->next = NULL;
            p = s;
        }
        else
        {
            head->next = s;
            s->next = p;
            p = s;
        }
        cin >> x;
    }
    return head;
}

void delx(node *head, datatype x) //先找到x的位置,再利用p及其前节点s修改s节点的指向,再释放删除节点的内存,
{
    node *p = head->next;
    node *s = head;
    while (p && p->data != x)
    {
        p = p->next;
        s = s->next;
    }
    if (!p)
    {
        cout << "没有找到值为x的数" << endl;
        return;
    }
    s->next = p->next;
    free(p);
}

void reverse(node *head) //利用头插法原理进行倒置,修改指针指向.
{
    node *p = head->next;
    node *s = head->next->next;
    node *temp;
    p->next = NULL;
    while (s)
    {
        temp = s->next;
        s->next = p;
        p = s;
        s = temp;
    }
    head->next = p;
}

void insert(node *head, datatype x) //比较大小找到要插入的位置,由前后两节点连接.
{
    node *p = head->next;
    node *s = head;
    node *temp = new node;
    temp->data = x;
    while (p && p->data < x)
    {
        p = p->next;
        s = s->next;
    }
    s->next = temp;
    temp->next = p;
}

void delallx(node *head, datatype x) //一个个找x的值,找到清除,直至遍历完整个链表
{
    node *p = head->next;
    node *s = head;
    while (p)
    {
        if (p->data == x)
        {
            s->next = p->next;
            free(p);
            p = s->next;
        }
        else
        {
            s = s->next;
            p = p->next;
        }
    }
}

void sort(node *head) //将头结点及第一个结点分离,采用插入排序,从剩余链表中一个个将结点根据大小插入head中合适的位置
{
    node *p = head->next->next;
    head->next->next = NULL;
    while (p)
    {
        node *temp = p;
        node *q = head->next;
        node *w = head;
        while (q && q->data < p->data)
        {
            q = q->next;
            w = w->next;
        }
        p = p->next;
        w->next = temp;
        temp->next = q;
    }
}

node *mergeascend(node *l1, node *l2) //由于按升序排列好了,所以直接将两链表一个一个比大小,小的进新链
// 当一链遍历完之后,另一条链直接进新链
{
    node *l3;
    l3 = init();
    l1 = l1->next;
    l2 = l2->next;
    node *q;
    q = l3;
    while (l1 || l2)
    {
        if (l1 && l2)
        {
            if (l1->data > l2->data)
            {
                q->next = l2;
                l2 = l2->next;
                q = q->next;
            }
            else if (l1->data < l2->data)
            {
                q->next = l1;
                l1 = l1->next;
                q = q->next;
            }
            else if (l1->data == l2->data)
            {
                q->next = l1;
                q = q->next;
                l1 = l1->next;
                q->next = l2;
                q = q->next;
                l2 = l2->next;
            }
        }
        else if (!l1)
        {
            q->next = l2;
            l2 = l2->next;
            q = q->next;
        }
        else if (!l2)
        {
            q->next = l1;
            l1 = l1->next;
            q = q->next;
        }
    }
    q->next = NULL;
    return l3;
}

node *mergedescend(node *l1, node *l2) //先合成一条升序链表,再将链表倒置就行(前面写过就直接调用)
{
    node *l3 = mergeascend(l1, l2);
    reverse(l3);
    return l3;
}

node *intersection(node *l1, node *l2) //求交集,直接两重循环找到所有相同元素,由于可能有重复元素,
//所以用一个标识检测新链中是否有重复元素
{
    l1 = l1->next;
    l2 = l2->next;
    node *l3;
    l3 = init();
    node *p = l3;
    while (l1)
    {
        node *q = l2;
        int flag = 1;
        int biao = 0;
        while (q)
        {
            if (l1->data == q->data)
            {
                node *t = l3->next;
                while (t)
                {
                    if (t->data == l1->data)
                    {
                        flag = 0;
                        break;
                    }
                    t = t->next;
                }
                if (flag == 1)
                {
                    biao = 1;
                    p->next = l1;
                    p = p->next;
                    l1 = l1->next;
                    p->next = NULL;
                }
                break;
            }
            q = q->next;
        }
        if (biao == 0)
        {
            node *temp = l1;
            l1 = l1->next;
            free(temp);
        }
    }
    return l3;
}

void partion(node *head) //遍历整个链表,找到奇数就将奇数插入头结点的后面。第一个结点为奇数就特殊处理。
{
    node *s = head;
    node *p = head->next;
    if (head->next->data % 2 == 1)
    {
        p = p->next;
        s = s->next;
    }
    while (p)
    {

        if (p->data % 2 == 1)
        {
            s->next = p->next;
            p->next = head->next;
            head->next = p;
            p = s->next;
        }
        else
        {
            p = p->next;
            s = s->next;
        }
    }
}

node *search(node *head, int k) //将链表倒置,就转换为寻找正数第k个数。
{
    reverse(head);
    node *p = head->next;
    int cnt = 1;
    while (p)
    {
        if (cnt == k)
        {
            break;
        }
        cnt++;
        p = p->next;
    }
    return p;
}

void dellist(node *head)
{
    node *p = head;
    while (p)
    {
        p = p->next;
        free(head);
        head = p;
    }
}

int main()
{
    // node *head;
    // head = createbyqueue();
    // output(head);//实验5
    // sort(head);
    // output(head);
    // dellist(head);

    // node *l1, *l2, *l3;
    // cout << "请输入升序的数字" << endl;
    // l1 = createbyqueue();
    // cout << "请输入升序的数字" << endl;
    // l2 = createbyqueue();
    // output(l1);
    // output(l2);//实验6
    // l3 = mergeascend(l1, l2);
    // l3 = mergedescend(l1, l2);
    // output(l3);
    // dellist(l3);

    // node *l1, *l2, *l3;
    // l1 = createbyqueue();
    // l2 = createbyqueue();
    // output(l1);
    // output(l2);
    // l3 = intersection(l1, l2);//实验7
    // output(l3);
    // dellist(l2);
    // dellist(l3);

    // node *head;
    // head = createbyqueue();
    // output(head);//实验8
    // partion(head);
    // output(head);
    // dellist(head);

    node *head, *p;
    int k;
    head = createbyqueue();
    cout << "请输入要查找的倒数第k个数:";
    cin >> k;
    p = search(head, k);//实验9
    if (!p)
        cout << "k太大了,无法找到" << endl;
    else
        cout << "倒数第k个数值为:" << p->data << endl;
    dellist(head);

    

    system("pause");
    return 0;
}

4.调试过程及运行结果(详细记录在调试过程中出现的问题及解决方法。记录实验执行的结果)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辉哥哥哟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值