数据结构与算法实验1——线性表的应用之双向链表

线性表的应用之双向链表

一、目的要求
1.掌握双向链表的存储结构及其实现。
2.掌握双向链表的插入与删除算法的程序实现。
二、实验内容
1.利用尾插法建立一个双向链表。
2.遍历双向链表。
3.实现双向链表中删除一个指定元素。
4.在非递减有序双向链表中实现插入元素 e 仍有序的算法。
5.判断双向链表中元素是否对称,若对称返回 1,否则返回 0。
6.设元素为正整型,实现算法把所有奇数排列在偶数之前。
7.在主函数中设计一个简单菜单,调用上述算法。
三、实验说明

  1. 双向链表的类型定义
    typedef int ElemType; // 元素类型
    typedef struct DuLNode
    {
    ElemType data;
    DuLNode *prior, *next;
    } DuLNode, *pDuLinkList;

四、代码
(一)头文件

#pragma once
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;

typedef int ElemType; // 元素类型
typedef struct DuLNode
{
	ElemType data;
	DuLNode* prior, * next;//双指针
} DuLNode, * pDuLinkList;

//尾插法建立链表
pDuLinkList CreatList_Tail()
{
    pDuLinkList q;
    pDuLinkList head = (pDuLinkList)malloc(sizeof(struct DuLNode));//申请头结点空间
    head->next = NULL;
    head->prior = NULL;
    q = head;
    srand((unsigned)time(NULL));//随机函数的种子,用于不同时间生成的数据不一样
    cout << "请输入你想要建立的链表长度:";
    int len;
    cin >> len;
    for (int i = 0; i < len; i++)
    {
        pDuLinkList p= (pDuLinkList)malloc(sizeof(struct DuLNode));
        q->next = p;
        p->next = NULL;
        p->prior = q;
        q = p;
        p->data = rand() % 100;//随机生成0到100的数
    }
    cout << "恭喜你!创建成功!!!"<<endl;
    return head;
}


void ShowList(pDuLinkList head)//遍历
{
    pDuLinkList q = head->next;
    cout << "遍历的结果为:";
    while (q!= NULL)
    {
        cout << q->data<<"  ";
        q = q->next;
    }
    cout << "\n";
}

void DeleteData(pDuLinkList head,int x)//删除元素
{
    pDuLinkList q = head->next;
    pDuLinkList p = head;
    for (int i = 0; i < 30; i++)//30是在用户输入的长度比较小的情况下
    {
        if (q->data==x)
        {
            p->next = q->next;//改变指针指向
            q->next->prior = p;
            free(q);//释放空间
            break;
        }
        else
        {
             q = q->next;//向后移一个结点
             p = p->next;
        }
       
    }
}


pDuLinkList OrderList(pDuLinkList head)//重新排序链表,使其成为递增
{
    pDuLinkList q, p,min;
    min = NULL;
    int temp;
    for (p = head->next; p; p = p->next)//循环p指针
    {
        min = p;
        for (q=p->next;q;q=q->next)//q为p的后继结点,此循环用来找这个链表的最小值
        {
            if (q->data < min->data)//交换数据
            {
                min = q;
            }    
        } 
            temp = p->data;
            p->data = min->data;
            min->data = temp;
    }
    return head;
}


pDuLinkList Insert_OrderList(pDuLinkList head,int x)//插入元素仍然是递增
{
    pDuLinkList p;
    pDuLinkList q=(pDuLinkList)malloc(sizeof(struct DuLNode));
    q->data = x;
    q->next = NULL;
    q->prior = NULL;
    for (p = head->next; p; p = p->next)
    {
        if (q->data < p->data)//修改四个指针指向,注意修改的顺序
        {
            q->next = p;
            q->prior = p->prior;
            p->prior ->next= q;
            p->prior = q;
            break;
        }
    }
    return head;
}

int Judge_Symmetry(pDuLinkList head)//判断元素对称,判断两边是否相等
{
    pDuLinkList q, p;
    p = head->next;
    q = head->next;
    int count = 0;
    while (p->next!=NULL)//循环把p指向最后一个
    {
        p = p->next;
        count++;//计数器记录结点个数
    }

    for (int i = 0; i < (count/2); i++)
    {
        if (q->data != p->data)//如果一对不想等则不对称
        {
            cout << "不对称!!!" << endl;
            return 0;
        }
        q = q->next;
        p = p->prior;
    }
    cout << "对称!!!" << endl;
    return 1;
}

pDuLinkList Odd_Even(pDuLinkList head)//奇数前偶数后-用求模%2等于0为偶数,1位奇数-把偶数结点提取出来链接成一个链表再加到奇数后面
{
    pDuLinkList q,p,t,evenhead,qpre;
    evenhead = (pDuLinkList)malloc(sizeof(struct DuLNode));//偶数头结点
    evenhead->data = NULL;
    evenhead->next = NULL;
    evenhead->prior = NULL;
    t = evenhead;//偶数链表临时结点
    q = head->next; //奇数链表临时结点
    p = head;//用来辅助计算元素个数
    qpre = head;//q结点的前驱结点
    int count = 0;
    while (p->next != NULL)//循环把p指向最后一个
    {
        count++;//计数器记录结点个数
        p = p->next;
    }
    for (int i = 0; i < count; i++)
    {
        if ((q->data) % 2 == 1)//奇数
        { 
            qpre = q;
            if (q->next == NULL)//判断当前结点是否是最后一个,防止继续执行q为空
            {
                break;
            }
            q = q->next; 
        }
        else//否则就是偶数-把偶数结点提取出来生成新链表
        {
            if (q->next == NULL)break;//最后一个结点时停止
            qpre->next = q->next;//q的前驱指向q的后继
            q->next->prior = q->prior;//q的后继指向q的前驱
            t->next = q;//偶数链表临时结点指向q
            t->next->prior = t;//q的前驱指向t
            t = q;//t向下移到q位置
            q = q->next;//开始下一个结点的判断
            t->next = NULL;//必须设置为空,否则t会连着奇数表
        }
    }
    q->next = evenhead->next;//;//再把奇数表链接偶数表为一个表
    evenhead->next->prior = q;
    free(evenhead);
    return head;
}
/*
    菜单界面
*/

//定义主菜单
int Out();
void Menu() {
    bool opt = true;        //是否循环的一个标志
    while (opt == true) {

        //菜单列表
        cout << "\n\t\t**********************************\n";
        cout << "\t\t*   1.     建立双向链表          *\n";
        cout << "\t\t*   2.       遍历 链表           *\n";
        cout << "\t\t*   3.       删除 元素           *\n";
        cout << "\t\t*   4. 建立递增有序表并插入元素  *\n";
        cout << "\t\t*   5.       判断元素对称        *\n";
        cout << "\t\t*   6.       奇数前偶数后        *\n";
        cout << "\t\t*   7.         退 出             *\n";
        cout << "\t\t**********************************\n";

        //接收输入选择
        cout << "\t\t请选择算法:";
        char x;
        cin >> x;

        //判断用户的选择
        switch (x) {
        case '1':
            cout << "\n\t\t你选择了1\n";
            pDuLinkList list1;
            list1=CreatList_Tail();
            opt = Out();        //小目录
            break;
        case '2':
            std::cout << "\n\t\t你选择了2\n";
            pDuLinkList list2;
            list2 = CreatList_Tail();
            ShowList(list2);
            opt = Out();        //小目录
            break;
        case '3':
            cout << "\n\t\t你选择了3\n";
            pDuLinkList list3;
            list3= CreatList_Tail();//创建一个链表
            ShowList(list3);//遍历原链表
            cout << "\n";
            cout << "请输入你想要删除的元素:";
            int x;
            cin >> x;
            DeleteData(list3,x);//删除元素
            ShowList(list3);//遍历删除元素后的链表
            opt = Out();        //小目录
            break;
        case '4':
            cout << "\n\t\t你选择了4\n";
            pDuLinkList list4;
            list4 = CreatList_Tail();//创建一个链表
            ShowList(list4);
            //把生成的链表重新排序
            
            ShowList(OrderList(list4));//遍历重新生成的排序递增链表
            //再插入一个元素仍然是递增
            cout << "请输入你想要插入的元素:";
            int y;
            cin >> y;
            ShowList(Insert_OrderList(list4, y));

            opt = Out();        //小目录
            break;
        case '5':
            cout << "\n\t\t你选择了5\n";
            pDuLinkList list6;
            list6 = CreatList_Tail();//创建一个链表
            Judge_Symmetry(list6);

            opt = Out();        //小目录
            break;
        case '6':
            cout << "\n\t\t你选择了6\n";
            pDuLinkList list7;
            list7 = CreatList_Tail();//创建一个链表
            ShowList(list7);
            ShowList(Odd_Even(list7));
            opt = Out();        //小目录
            break;
        case '7':
            cout << "\n\t\t你选择了7\n";

            opt = false;        //把标志位为假,就退出了循环
            break;
        default:
            cout << "\n\t\t输入非法,请重新选择!\n";

            break;
        }

    }

    cout << "\n\t\t菜单已退出!\n";
}

//定义小目录
int Out() {

    cout << "\n";
    cout << "\t\t************\n";
    cout << "\t\t*1.返回目录*\n";
    cout << "\t\t*2.退出程序*\n";
    cout << "\t\t************\n";

    cout << "\t\t选择:";
    char y;
    cin >> y;      //接受输入
    switch (y) {
    case '1':
        return true;

    case '2':
        return false;

    default:
        cout << "\t\t非法输入,已返回主目录!\n";//输入其他数字无效
        return true;
        break;
    }
}

(二)源文件

/*
实验名称:双向链表
实验目的:
1.掌握双向链表的存储结构及其实现。
2.掌握双向链表的插入与删除算法的程序实现
实验内容:
1.利用尾插法建立一个双向链表。
2.遍历双向链表。
3.实现双向链表中删除一个指定元素。
4.在非递减有序双向链表中实现插入元素 e 仍有序的算法。
5.判断双向链表中元素是否对称,若对称返回 1,否则返回 0。
6.设元素为正整型,实现算法把所有奇数排列在偶数之前。
7.在主函数中设计一个简单菜单,调用上述算法
实验日期:2020/11/27
开发者:每天八杯水
*/
#include<iostream>
#include"双向链表.h"

pDuLinkList CreatList_Tail();
void ShowList();
void DeleteData();
pDuLinkList OrderList();//排序递增
pDuLinkList Insert_OrderList();//插入元素
int Judge_Symmetry();//判断对称
pDuLinkList Odd_Even();
void Menu();
int Out();

int main()
{
	Menu();
}

(三)运行截图


                **********************************
                *   1.     建立双向链表          *
                *   2.       遍历 链表           *
                *   3.       删除 元素           *
                *   4. 建立递增有序表并插入元素  *
                *   5.       判断元素对称        *
                *   6.       奇数前偶数后        *
                *   7.         退 出             *
                **********************************
                请选择算法:1

                你选择了1
请输入你想要建立的链表长度:12
恭喜你!创建成功!!!

                ************
                *1.返回目录*
                *2.退出程序*
                ************
                选择:1

                **********************************
                *   1.     建立双向链表          *
                *   2.       遍历 链表           *
                *   3.       删除 元素           *
                *   4. 建立递增有序表并插入元素  *
                *   5.       判断元素对称        *
                *   6.       奇数前偶数后        *
                *   7.         退 出             *
                **********************************
                请选择算法:2

                你选择了2
请输入你想要建立的链表长度:12
恭喜你!创建成功!!!
遍历的结果为:61  54  91  22  40  78  0  34  61  42  59  49

                ************
                *1.返回目录*
                *2.退出程序*
                ************
                选择:1

                **********************************
                *   1.     建立双向链表          *
                *   2.       遍历 链表           *
                *   3.       删除 元素           *
                *   4. 建立递增有序表并插入元素  *
                *   5.       判断元素对称        *
                *   6.       奇数前偶数后        *
                *   7.         退 出             *
                **********************************
                请选择算法:3

                你选择了3
请输入你想要建立的链表长度:11
恭喜你!创建成功!!!
遍历的结果为:77  28  76  67  77  44  63  65  83  69  19

请输入你想要删除的元素:77
遍历的结果为:28  76  67  77  44  63  65  83  69  19

                ************
                *1.返回目录*
                *2.退出程序*
                ************
                选择:1

                **********************************
                *   1.     建立双向链表          *
                *   2.       遍历 链表           *
                *   3.       删除 元素           *
                *   4. 建立递增有序表并插入元素  *
                *   5.       判断元素对称        *
                *   6.       奇数前偶数后        *
                *   7.         退 出             *
                **********************************
                请选择算法:4

                你选择了4
请输入你想要建立的链表长度:7
恭喜你!创建成功!!!
遍历的结果为:4  12  50  65  57  90  94
遍历的结果为:4  12  50  57  65  90  94
请输入你想要插入的元素:0
遍历的结果为:0  4  12  50  57  65  90  94

                ************
                *1.返回目录*
                *2.退出程序*
                ************
                选择:1

                **********************************
                *   1.     建立双向链表          *
                *   2.       遍历 链表           *
                *   3.       删除 元素           *
                *   4. 建立递增有序表并插入元素  *
                *   5.       判断元素对称        *
                *   6.       奇数前偶数后        *
                *   7.         退 出             *
                **********************************
                请选择算法:5

                你选择了5
请输入你想要建立的链表长度:4
恭喜你!创建成功!!!
不对称!!!

                ************
                *1.返回目录*
                *2.退出程序*
                ************
                选择:6
                非法输入,已返回主目录!

                **********************************
                *   1.     建立双向链表          *
                *   2.       遍历 链表           *
                *   3.       删除 元素           *
                *   4. 建立递增有序表并插入元素  *
                *   5.       判断元素对称        *
                *   6.       奇数前偶数后        *
                *   7.         退 出             *
                **********************************
                请选择算法:6

                你选择了6
请输入你想要建立的链表长度:8
恭喜你!创建成功!!!
遍历的结果为:59  26  29  25  97  8  38  20
遍历的结果为:59  29  25  97  20  26  8  38

                ************
                *1.返回目录*
                *2.退出程序*
                ************
                选择:

五、思考总结
1.在对算法6进行设计的时候考虑得不细致,导致调试了很长时间,这就是架构整体不全的后果,所以思维严谨非常重要,我需要多多练习;最后当调试不出来的时候不要急躁,拿上笔和纸慢慢分析,我就是关上电脑去远动远动看看其他风景最后回来灵感就来了,加油加油加油奥利给!!!
谢谢您的浏览,由于水平有限,很多地方有待提高,若您有更好的建议欢迎留言!————————————每天八杯水

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值