菜单
cpp
//0、显示菜单
void menu()
{
cout << "菜单:" << endl;
cout << "1.初始化或重置链表" << endl;
cout << "2.销毁链表" << endl;
cout << "3.清空链表" << endl;
cout << "4.链表长度" << endl;
cout << "5.指定位置的元素值" << endl;
cout << "6.链表已存在元素的位序" << endl;
cout << "7.求输入元素的直接前驱" << endl;
cout << "8.求输入元素的直接后继" << endl;
cout << "9.在第i个位置插入一个元素" << endl;
cout << "10.删除第i个元素" << endl;
cout << "11.输出有的链表元素" << endl;
cout << "12.初始化并用头插法(或尾插法)输入元素" << endl;
cout << "13.实现单链表的逆序存放" << endl;
cout << "-1.退出程序" << endl;
}
定义结构体
cpp
// 定义结构体
typedef struct DNode
{
EleType data;
struct DNode *prior,*next;
}Dnode,*DLinkList;
1.初始化或重置链表
cpp
// 1、初始化双向链表
bool Init_linkList(DLinkList& L)
{
L = (DNode*) malloc(sizeof(DNode));
if(L == nullptr)
return false;
else
{
L->prior = nullptr;
L->next = nullptr;
return true;
}
}
2.销毁链表
注:销毁链表时需要循环释放每个结点所占用的空间。
cpp
// 2、销毁链表
void DestroyLink(DNode *L){//为了避免内存泄露,每次创建链表运行完程序应将创建的链表销毁,避免内存泄露
DNode *temp;
DNode *pre;
temp= L->next;
while(temp != nullptr){
pre = temp;
temp = temp->next;
free(pre);
}
free(L);
}
3.清空链表
cpp
// 3、清空双链表
bool ClearDLink(DNode* L)
{
DNode *temp;
DNode *pre;
temp= L->next;
while(temp != nullptr){
pre = temp;
temp = temp->next;
free(pre);
}
L->next = nullptr;
L->prior = nullptr;
if(L->next == nullptr)
return true;
else
return false;
}
4.链表长度
cpp
// 4、求双链表长度
int LengthLink(Dnode*L)
{
int cnt = 0;
DNode *temp;
temp= L->next;
while(temp != nullptr){
temp = temp->next;
cnt ++;
}
return cnt;
}
5.指定位置的元素值
cpp
// 5、指定位置元素
int elem_check(Dnode*L,int address)// 判断这个位置是否合法
{
int cnt = LengthLink(L);
if(address <= 0 || address > cnt) return false;
return true;
}
EleType ElemLink(Dnode *L,int address)// 如果这个位置合法,则进行查找
{
int cnt = 0;
EleType flag;
DNode *temp;
DNode *pre;
temp= L->next;
while(temp != nullptr){
pre = temp;
temp = temp->next;
if(++ cnt == address) flag = pre->data;
}
return flag;
}
6.链表已存在元素的位序
cpp
// 6.链表已存在元素的位序
bool judge_address(Dnode *L,EleType elem)
{
DNode *temp;
temp= L->next;
while(temp != nullptr){
if(temp->data == elem) return true;
temp = temp->next;
}
return false;
}
int AddressLink(Dnode *L,EleType elem)
{
int address = 0;
int cnt = 0;
DNode *temp;
temp= L->next;
while(temp != nullptr){
cnt ++;
if(temp->data == elem) address = cnt;
temp = temp->next;
}
return address;
}
7.求输入元素的直接前驱
cpp
// 7.求输入元素的直接前驱
bool judge_before(Dnode *L,EleType elem)
{
DNode *temp;
temp= L->next;
while(temp != nullptr){
if(temp->data == elem)
{
if(temp->prior == L) return false;
else return true;
}
temp = temp->next;
}
return false;
}
EleType BeforeLink(Dnode *L,EleType elem)
{
EleType flag;
DNode *temp;
temp= L->next;
while(temp != nullptr){
if(temp->data == elem)
{
flag = temp->prior->data;
}
temp = temp->next;
}
return flag;
}
求前驱是指,输入一个元素值(而不是位置),求该元素在顺序表中的直接前驱元素值。
8.求输入元素的直接后继
cpp
// 8.求输入元素的直接后继
bool judge_after(Dnode *L,EleType elem)
{
DNode *temp;
temp= L->next;
while(temp != nullptr){
if(temp->data == elem)
{
if(temp->next == nullptr) return false;
else return true;
}
temp = temp->next;
}
return false;
}
EleType AfterLink(Dnode *L,EleType elem)
{
EleType flag;
DNode *temp;
temp= L->next;
while(true){
if(temp->data == elem)
{
flag = temp->next->data;
break;
}
temp = temp->next;
}
return flag;
}
求后继是指:输入一个元素值(而不是位置),求该元素在顺序表中的直接后继元素值。
9.在第i个位置插入一个元素
cpp
// 9.在第i个位置插入一个元素
void LinkListInit(Dnode* L,int address,EleType elem)
{
Dnode* l;
l = (DNode*) malloc(sizeof(DNode));
l->data = elem;
int cnt = 0;
DNode *temp;
temp= L->next;
int len = LengthLink(L);
if(address == len + 1)
{
temp = L;
while(true)
{
if(temp->next == nullptr)
{
l->next = nullptr;
l->prior = temp;
temp->next = l;
return;
}
temp = temp->next;
}
}
else
{
while(temp != nullptr){
cnt ++;
if(cnt == address)
{
l->next = temp;
l->prior = temp->prior;
temp->prior->next = l;
temp->prior = l;
return;
}
temp = temp->next;
}
}
}
10.删除第i个元素
cpp
// 10.删除第i个元素
void drop(Dnode* L,int address)
{
int cnt = 0;
DNode *temp;
temp= L->next;
int len = LengthLink(L);
if(len == address)
{
while(true)
{
if(temp->next == nullptr)
{
temp->prior->next = nullptr;
free(temp);
return;
}
temp = temp->next;
}
}
while(temp != nullptr){
cnt ++;
if(cnt == address)
{
temp->prior->next = temp->next;
temp->next->prior = temp->prior;
free(temp);
return;
}
temp = temp->next;
}
}
11.输出有的链表元素
cpp
// 11.输出有的链表元素
void show(Dnode* L)
{
DNode *temp;
temp= L->next;
while(temp != nullptr){
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
12.清空链表并用头插法(或尾插法)输入元素
cpp
// 12.清空并用头插法(或尾插法)输入元素
void show12(Dnode* L,int sum)
{
ClearDLink(L);
for(int i = 0; i < sum; i ++)
{
Dnode* l;
l = (DNode*) malloc(sizeof(DNode));
EleType num;
cin >> num;
l->data = num;
l->next = L->next;
l->prior = L;
if(L->next != nullptr)
{
L->next->prior = l;
}
L->next = l;
}
show(L);
}
13.实现单链表的逆序存放
cpp
void show13(Dnode* L)
{
queue<EleType> q;
DNode *temp;
DNode *p;
temp= L->next;
while(temp != nullptr){
q.push(temp->data);
p = temp;
temp = temp->next;
free(p);
}
L->next = nullptr;
L->prior = nullptr;
while(!q.empty())
{
EleType s;
s = q.front();
q.pop();
DNode* l;
l = (Dnode*) malloc(sizeof(DNode));
l->data = s;
l->next = L->next;
l->prior = L;
if(L->next != nullptr)
{
L->next->prior = l;
}
L->next = l;
}
}
要求:所有的提示语和输出语句不允许出现在自定义的函数中(输出函数除外),只能在main函数中出现提示语。
注意,每个功能模块一定要考虑非法的情况,并作出相应的提示,例如:求前驱,要分别能够测试第一个元素的前驱、其他正常的元素的前驱、输入一个在表中不存在的元素求其前驱,这三种情况应给出相应的提示语和结果值;插入和删除时要考虑插入或删除的位置是否合法等。
代码
cpp
#include<bits/stdc++.h>
using namespace std;
typedef int EleType;
// 定义结构体
typedef struct DNode
{
EleType data;
struct DNode *prior,*next;
}Dnode,*DLinkList;
//0、显示菜单
void menu()
{
cout << "菜单:" << endl;
cout << "1.初始化或重置链表" << endl;
cout << "2.销毁链表" << endl;
cout << "3.清空链表" << endl;
cout << "4.链表长度" << endl;
cout << "5.指定位置的元素值" << endl;
cout << "6.链表已存在元素的位序" << endl;
cout << "7.求输入元素的直接前驱" << endl;
cout << "8.求输入元素的直接后继" << endl;
cout << "9.在第i个位置插入一个元素" << endl;
cout << "10.删除第i个元素" << endl;
cout << "11.输出有的链表元素" << endl;
cout << "12.初始化并用头插法(或尾插法)输入元素" << endl;
cout << "13.实现单链表的逆序存放" << endl;
cout << "-1.退出程序" << endl;
}
// 1、初始化双向链表
bool Init_linkList(DLinkList& L)
{
L = (DNode*) malloc(sizeof(DNode));
if(L == nullptr)
return false;
else
{
L->prior = nullptr;
L->next = nullptr;
return true;
}
}
// 2、销毁链表
void DestroyLink(DNode *L){//为了避免内存泄露,每次创建链表运行完程序应将创建的链表销毁,避免内存泄露
DNode *temp;
DNode *pre;
temp= L->next;
while(temp != nullptr){
pre = temp;
temp = temp->next;
free(pre);
}
free(L);
}
// 3、清空双链表
bool ClearDLink(DNode* L)
{
DNode *temp;
DNode *pre;
temp= L->next;
while(temp != nullptr){
pre = temp;
temp = temp->next;
free(pre);
}
L->next = nullptr;
L->prior = nullptr;
if(L->next == nullptr)
return true;
else
return false;
}
// 4、求双链表长度
int LengthLink(Dnode*L)
{
int cnt = 0;
DNode *temp;
temp= L->next;
while(temp != nullptr){
temp = temp->next;
cnt ++;
}
return cnt;
}
// 5、指定位置元素
int elem_check(Dnode*L,int address)
{
int cnt = LengthLink(L);
if(address <= 0 || address > cnt) return false;
return true;
}
EleType ElemLink(Dnode *L,int address)
{
int cnt = 0;
EleType flag;
DNode *temp;
DNode *pre;
temp= L->next;
while(temp != nullptr){
pre = temp;
temp = temp->next;
if(++ cnt == address) flag = pre->data;
}
return flag;
}
// 6.链表已存在元素的位序
bool judge_address(Dnode *L,EleType elem)
{
DNode *temp;
temp= L->next;
while(temp != nullptr){
if(temp->data == elem) return true;
temp = temp->next;
}
return false;
}
int AddressLink(Dnode *L,EleType elem)
{
int address = 0;
int cnt = 0;
DNode *temp;
temp= L->next;
while(temp != nullptr){
cnt ++;
if(temp->data == elem) address = cnt;
temp = temp->next;
}
return address;
}
// 7.求输入元素的直接前驱
bool judge_before(Dnode *L,EleType elem)
{
DNode *temp;
temp= L->next;
while(temp != nullptr){
if(temp->data == elem)
{
if(temp->prior == L) return false;
else return true;
}
temp = temp->next;
}
return false;
}
EleType BeforeLink(Dnode *L,EleType elem)
{
EleType flag;
DNode *temp;
temp= L->next;
while(temp != nullptr){
if(temp->data == elem)
{
flag = temp->prior->data;
}
temp = temp->next;
}
return flag;
}
// 8.求输入元素的直接后继
bool judge_after(Dnode *L,EleType elem)
{
DNode *temp;
temp= L->next;
while(temp != nullptr){
if(temp->data == elem)
{
if(temp->next == nullptr) return false;
else return true;
}
temp = temp->next;
}
return false;
}
EleType AfterLink(Dnode *L,EleType elem)
{
EleType flag;
DNode *temp;
temp= L->next;
while(true){
if(temp->data == elem)
{
flag = temp->next->data;
break;
}
temp = temp->next;
}
return flag;
}
// 9.在第i个位置插入一个元素
void LinkListInit(Dnode* L,int address,EleType elem)
{
Dnode* l;
l = (DNode*) malloc(sizeof(DNode));
l->data = elem;
int cnt = 0;
DNode *temp;
temp= L->next;
int len = LengthLink(L);
if(address == len + 1)
{
temp = L;
while(true)
{
if(temp->next == nullptr)
{
l->next = nullptr;
l->prior = temp;
temp->next = l;
return;
}
temp = temp->next;
}
}
else
{
while(temp != nullptr){
cnt ++;
if(cnt == address)
{
l->next = temp;
l->prior = temp->prior;
temp->prior->next = l;
temp->prior = l;
return;
}
temp = temp->next;
}
}
}
// 10.删除第i个元素
void drop(Dnode* L,int address)
{
int cnt = 0;
DNode *temp;
temp= L->next;
int len = LengthLink(L);
if(len == address)
{
while(true)
{
if(temp->next == nullptr)
{
temp->prior->next = nullptr;
free(temp);
return;
}
temp = temp->next;
}
}
while(temp != nullptr){
cnt ++;
if(cnt == address)
{
temp->prior->next = temp->next;
temp->next->prior = temp->prior;
free(temp);
return;
}
temp = temp->next;
}
}
// 11.输出有的链表元素
void show(Dnode* L)
{
DNode *temp;
temp= L->next;
while(temp != nullptr){
cout << temp->data << " ";
temp = temp->next;
}
cout << endl;
}
// 12.初始化并用头插法(或尾插法)输入元素
void show12(Dnode* L,int sum)
{
ClearDLink(L);
for(int i = 0; i < sum; i ++)
{
Dnode* l;
l = (DNode*) malloc(sizeof(DNode));
EleType num;
cin >> num;
l->data = num;
l->next = L->next;
l->prior = L;
if(L->next != nullptr)
{
L->next->prior = l;
}
L->next = l;
}
show(L);
}
void show13(Dnode* L)
{
queue<EleType> q;
DNode *temp;
DNode *p;
temp= L->next;
while(temp != nullptr){
q.push(temp->data);
p = temp;
temp = temp->next;
free(p);
}
L->next = nullptr;
L->prior = nullptr;
while(!q.empty())
{
EleType s;
s = q.front();
q.pop();
DNode* l;
l = (Dnode*) malloc(sizeof(DNode));
l->data = s;
l->next = L->next;
l->prior = L;
if(L->next != nullptr)
{
L->next->prior = l;
}
L->next = l;
}
}
int main()
{
DLinkList L;
int op = -1;
bool flag = false;
menu();
while(op != 0)
{
cout << "<------------------------------>" << endl << "请输入你的选择:";
cin >> op;
if(op == 1)
{
// 1.初始化或重置链表
if(Init_linkList(L))
{
cout << "初始化成功!" << endl;
flag = true;
}
else cout << "初始化失败!" << endl;
}else if(op == 2)
{
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
// 2.销毁链表
DestroyLink(L);
flag = false;
cout << "成功销毁链表!" << endl;
}else if(op == 3)
{
// 3.清空链表
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
if(ClearDLink(L))
cout << "清空链表成功!" << endl;
else
cout << "清空链表失败!" << endl;
}else if(op == 4)
{
// 4.链表长度
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
int l = LengthLink(L);
cout << "链表长度为:" << l << endl;
}else if(op == 5)
{
// 5.指定位置的元素值
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
int address;
cout << "请输入位置:";
cin >> address;
if(elem_check(L,address))
{
EleType ans = ElemLink(L,address);
cout << "第" << address << "位置的元素为:" << ans << endl;
}
else
{
cout << "这个位置没有元素!" << endl;
}
}else if(op == 6)
{
// 6.链表已存在元素的位序
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
EleType elem;
cout << "请输入查找的元素:";
cin >> elem;
if(judge_address(L,elem))
{
int address = AddressLink(L,elem);
cout << "值" << elem << "的位置在" << address << endl;
}
else
{
cout << "链表中不存在这个值!" << endl;
}
}else if(op == 7)
{
// 7.求输入元素的直接前驱
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
EleType elem;
cout << "请输入查找的元素:";
cin >> elem;
if(judge_before(L,elem))
{
EleType ans;
ans = BeforeLink(L,elem);
cout << "元素" << elem << "的直接前驱为:" << ans << endl;
}
else
{
cout << "这个值没有直接前驱!" << endl;
}
}else if(op == 8)
{
// 8.求输入元素的直接后继
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
EleType elem;
cout << "请输入查找的元素:";
cin >> elem;
if(judge_after(L,elem))
{
EleType ans;
ans = AfterLink(L,elem);
cout << "元素" << elem << "的直接后继为:" << ans << endl;
}
else
{
cout << "这个值没有直接后继!" << endl;
}
}
else if(op == 9)
{
// 9.在第i个位置插入一个元素
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
int len;
len = LengthLink(L);
int address;
cout << "输入插入位置:";
cin >> address;
EleType elem;
cout << "输入插入元素:";
cin >> elem;
if(address < 1 || address > len + 1)
{
cout << "这个位置不能插入元素" << endl;
}
else
{
LinkListInit(L,address,elem);
cout << "插入成功!" << endl;
}
}
else if(op == 10)
{
// 10.删除第i个元素
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
int address;
cout << "请输入元素位置:";
cin >> address;
int len = LengthLink(L);
if(address < 1 || address > len)
{
cout << "这个位置不能删除"<< endl;
continue;
}
drop(L,address);
cout << "删除成功!" << endl;
}
else if(op == 11)
{
// 11.输出有的链表元素
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
show(L);
}
else if(op == 12)
{
// 12.初始化并用头插法(或尾插法)输入元素
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
cout << "初始化并用头插法(或尾插法)输入元素" << endl;
cout << "请输入插入元素个数:";
int sum;
cin >> sum;
show12(L,sum);
}
else if(op == 13)
{
// 13.实现单链表的逆序存放
if(!flag)
{
cout << "链表已被销毁" << endl;
continue;
}
show13(L);
}
else if(op == -1) break;
}
cout << "程序结束!" << endl;
}