Files
some-cpp-files/Practical-Teaching/Data-Sructure/3/3.cpp
T
2024-03-17 22:30:49 +08:00

248 lines
6.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 预编译命令
#include <stdio.h>
#include <stdlib.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -2
// 数据结构
typedef int Status;
typedef int ElemType;
typedef struct LNode
{
ElemType data;
struct LNode *next;
} LNode, *LinkList;
// 函数声明
int menu_select();
int menu_select();
void CreateList_L(LinkList &L, int n);
void PrintList_L(LinkList L);
Status GetElem_L(LinkList &L, int i, ElemType &e);
Status ListInsert_L(LinkList &L, int i, ElemType e);
Status ListDelete_L(LinkList &L, int i, ElemType &e);
int LocateElem_L(LinkList L, ElemType e);
// 主函数
int main()
{
LinkList L;
int n, i, e, k;
for (;;)
{
switch (menu_select())
{
case 1:
printf("请输入元素的个数:");
scanf("%d", &n);
CreateList_L(L, n);
printf("创建完成\n");
break;
case 2:
PrintList_L(L);
break;
case 3:
printf("请输入要查找的元素的位序:");
scanf("%d", &i);
if (GetElem_L(L, i, e) == OK) // 调用取元素函数,如果成功,返回元素值给 e
{
printf("第%d个元素的值是%d\n", i, e);
}
else // 如果失败,输出错误信息
{
printf("查找失败,不存在第%d个元素\n", i);
}
break;
case 4:
printf("请输入要插入的元素的位序和值,用空格隔开:");
scanf("%d %d", &i, &e);
if (ListInsert_L(L, i, e) == OK) // 调用插入函数,如果成功,输出插入成功信息
{
printf("插入成功\n");
}
else // 如果失败,输出错误信息
{
printf("插入失败,插入位置不合法\n");
}
break;
case 5:
printf("请输入要删除的元素的位序:");
scanf("%d", &i);
if (ListDelete_L(L, i, e) == OK) // 调用删除函数,如果成功,返回删除的元素值给 e,并输出删除成功信息
{
printf("删除成功,删除的元素值是%d\n", e);
}
else // 如果失败,输出错误信息
{
printf("删除失败,删除位置不合法\n");
}
break;
case 6:
printf("请输入要查找的元素的值:");
scanf("%d", &e);
k = LocateElem_L(L, e); // 调用查找函数(已知元素找位序),返回位序给 k
if (k != 0) // 如果 k 不为 0,说明找到了元素 e,并输出其位序
{
printf("找到了元素%d,它的位序是%d\n", e, k);
}
else // 如果 k 为 0,说明没有找到元素 e,并输出查找失败信息
{
printf("查找失败,不存在元素%d\n", e);
}
break;
case 0:
printf("程序结束,谢谢使用!\n\n");
exit(0);
}
}
return 0;
}
int menu_select()
{
int sn;
printf("\n显示菜单\n");
printf("1.创建\n");
printf("2.显示\n");
printf("3.取元素\n");
printf("4.插入\n");
printf("5.删除\n");
printf("6.查找\n");
printf("0.退出\n");
printf("输入 0-6:");
for (;;)
{
scanf("%d", &sn);
if (sn < 0 || sn > 6)
printf("\n输入错误,重选0-6:");
else
break;
}
return sn;
}
// 创建单链表,头插法,已知线性表的长度
void CreateList_L(LinkList &L, int n)
{
LinkList p;
int i;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
printf("请逆序输入%d个元素:\n", n);
for (i = n; i >= 1; i--)
{
p = (LinkList)malloc(sizeof(LNode));
scanf("%d", &p->data); // 格式输入字符串补出来
p->next = L->next;
L->next = p;
}
}
// 输出单链表
void PrintList_L(LinkList L)
{
LinkList p;
p = L->next;
printf("输出链表中的元素:\n");
while (p)
{
printf("%d\t", p->data);
p = p->next;
}
printf("\n");
}
// 取元素函数
Status GetElem_L(LinkList &L, int i, ElemType &e)
{
// 在单链表 L 中查找第 i 个元素,并将其值赋给 e
LinkList p; // 定义一个指针 p
int j; // 定义一个计数器 j
p = L->next; // 让 p 指向链表 L 的第一个结点
j = 1; // 初始化 j 为 1
while (p && j < i) // p 不为空且计数器 j 还没有等于 i 时,循环继续
{
p = p->next; // 让 p 指向下一个结点
j++; // 让 j 增加 1
}
if (!p || j > i) // 如果 p 为空或者 j 大于 i,说明第 i 个元素不存在
{
return ERROR; // 返回错误标志
}
e = p->data; // 取出第 i 个元素的数据,赋给 e
return OK; // 返回成功标志
}
// 插入函数
Status ListInsert_L(LinkList &L, int i, ElemType e)
{
// 在单链表 L 中的第 i 个位置插入新的元素 e
LinkList p, s; // 定义两个指针 p 和 s
int j; // 定义一个计数器 j
p = L; // 让 p 指向链表 L 的头结点
j = 0; // 初始化 j 为 0
while (p && j < i - 1) // 寻找第 i-1 个结点,p 指向该结点
{
p = p->next;
j++;
}
if (!p || j > i - 1) // 如果 p 为空或者 j 大于 i-1,说明插入位置不合法
{
return ERROR; // 返回错误标志
}
s = (LinkList)malloc(sizeof(LNode)); // 分配一个新的结点 s
s->data = e; // 将新元素 e 赋给 s 的数据域
s->next = p->next; // 将 s 的指针域指向 p 的后继结点
p->next = s; // 将 p 的指针域指向 s 结点
return OK; // 返回成功标志
}
// 删除函数
Status ListDelete_L(LinkList &L, int i, ElemType &e)
{
// 在单链表 L 中删除第 i 个元素,并用 e 返回其值
LinkList p, q; // 定义两个指针 p 和 q
int j; // 定义一个计数器 j
p = L; // 让 p 指向链表 L 的头结点
j = 0; // 初始化 j 为 0
while (p->next && j < i - 1) // 寻找第 i-1 个结点,p 指向该结点,且保证 p 的后继不为空(即第 i 个结点存在)
{
p = p->next;
j++;
}
if (!(p->next) || j > i - 1) // 如果 p 的后继为空或者 j 大于 i-1,说明删除位置不合法
{
return ERROR; // 返回错误标志
}
q = p->next; // 让 q 指向要删除的结点(即第 i 个结点)
p->next = q->next; // 将 q 的后继赋给 p 的后继(即相当于断开了 q 结点)
e = q->data; // 将 q 结点的数据赋给 e(用于返回)
free(q); // 释放 q 结点的空间
return OK; // 返回成功标志
}
// 查找函数(已知元素找位序)
int LocateElem_L(LinkList L, ElemType e)
{
LinkList p;
int i;
p = L->next;
i = 1;
while (p && p->data != e) // 从第一个结点开始,遍历链表,直到找到元素 e 或者链表结束
{
p = p->next;
i++;
}
if (p) // 如果找到了元素 e,返回其位序 i
{
return i;
}
else // 如果没有找到元素 e,返回 0
{
return 0;
}
}