线性表的应用之双向链表
一、目的要求
1.掌握双向链表的存储结构及其实现。
2.掌握双向链表的插入与删除算法的程序实现。
二、实验内容
1.利用尾插法建立一个双向链表。
2.遍历双向链表。
3.实现双向链表中删除一个指定元素。
4.在非递减有序双向链表中实现插入元素 e 仍有序的算法。
5.判断双向链表中元素是否对称,若对称返回 1,否则返回 0。
6.设元素为正整型,实现算法把所有奇数排列在偶数之前。
7.在主函数中设计一个简单菜单,调用上述算法。
三、实验说明
- 双向链表的类型定义
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进行设计的时候考虑得不细致,导致调试了很长时间,这就是架构整体不全的后果,所以思维严谨非常重要,我需要多多练习;最后当调试不出来的时候不要急躁,拿上笔和纸慢慢分析,我就是关上电脑去远动远动看看其他风景最后回来灵感就来了,加油加油加油奥利给!!!
谢谢您的浏览,由于水平有限,很多地方有待提高,若您有更好的建议欢迎留言!————————————每天八杯水