实验报告3

实验报告3,第1张

带头结点的单链表

代码有点长,但能保证,逻辑没有基本错误,程序能正确运行。


(现在真的觉得链表很简单,加油,你也可以)

  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 
#include 
#include 
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.调试过程及运行结果(详细记录在调试过程中出现的问题及解决方法。


记录实验执行的结果)

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/563954.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-03
下一篇 2022-04-03

发表评论

登录后才能评论

评论列表(0条)

保存