#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#define Status int
#define ElemType int
using namespace std;
typedef struct LNode
{
ElemType data;
struct LNode * next;
}LNode, *LinkList;
/*****************基本操作函数**************/
//1.初始化链表——构造一个空表
//算法步骤:
// 1.生成新结点做头结点,用头指针L指向头结点
// 2.将头结点的指针域置空
Status InitList(LinkList &L)
{
L = new LNode; //生成头结点
L->next = NULL; //将头结点指针域置空
return 1;
}
//2.判断链表是否为空
//空表的定义:链表中无元素(头指针和头结点仍然存在)
//算法思路:判断头结点指针域是否为空
int ListEmpty(LinkList L) //空表返回1,非空返回0
{
if (L->next)
return 0;
else
return 1;
}
//3.销毁单链表
//算法思路:从头指针开始,依次释放所有结点
Status DestroyList(LinkList &L)
{
LinkList p;
while (L)
{
p = L; //p指向头结点
L = L->next; //L指向下一结点
delete p; //删除结点
}
return 1;
}
//4. 清空链表
//定义:链表仍然存在,但链表中无元素,成为空链表
//算法思路:依次释放所有结点,并将头指针指针域置空
Status ClearList(LinkList &L)
{
LinkList p, q;
p = L->next;
while (p)
{
q = p->next;
delete p;
p = q;
}
L->next = NULL; //头结点指针域置空
return 1;
}
//5.获取单链表长度
//算法思路:从首元结点开始,依次计数所有结点
int ListLength(LinkList L)
{
LinkList p;
p = L->next; //p指向首节点
int i = 0;
while (p) //遍历链表,统计节点数
{
p = p->next;
i++;
}
return i;
}
//6. 取第i个元素的值
//算法步骤:
// 1.从第1个结点(L->next)顺序扫描,用指针p指向当前扫描到的结点p的初值为p=L->next.
// 2.j做计数器,累计当前扫描过的节点数,j的初值为1
// 3.当p指向扫描到的下一结点时,计数器j加1
// 4.当j==i时,p所指向的结点就是要找的第i个结点
Status GetElem(LinkList L, int i, ElemType &e)
{
LinkList p;
p = L->next;
int j = 0;
while (p && j<i) //向后遍历,直到p指向第i个元素或p为空
{
p = p-> next;
++j;
}
if (!p || j>i) //第i个元素不存在
return 0;
e = p->data;
return 1;
}
//6.查找
//算法步骤:
// 1.从第一个结点起,依次和e相比较
// 2.如果找到一个其值与e相等的数据元素,则返回其在链表中的位置或地址
// 3.如果查遍整个链表都没有和e相等的元素,则返回0或者NULL
//
//6-1.查找——返回地址
LNode *LocateElem(LinkList L, ElemType e)
{
LinkList p;
p = L->next;
while (p && p->data != e)
{
p = p->next;
}
return p;
}
//6-2.查找——返回位置序号
//int LocateElem(LinkList L, ElemType e)
//{
// LinkList p;
// p = L->next;
// int j = 1;
// while (p && p->data != e)
// {
// p = p->next;
// j++;
// }
// if (p)
// return j;
// else
// return 0;
//}
//7.插入结点
//算法步骤:
// 1.首先找到ai-1的存储位置p
// 2.生成一个数据域为e的新节点s
// 3.插入新节点:1.新节点的指针域指向ai(s->next = p->next)
// 2.结点ai-1的指针域指向新节点
Status ListInsert(LinkList &L, int i, ElemType e)
{
LinkList p, s;
p = L;
int j = 0;
while (p && j < i-1) //寻找第i-1个结点,p指向第i-1个结点
{
p = p->next;
++j;
}
if (!p || j > i-1) //i大于表长+1或者小于1,位置非法
return 0;
s = new LNode; //生成结点s
s->data = e;
s->next = p->next; //将s插入链表中
p->next = s;
return 1;
}
//8.删除第i个结点
//算法步骤:
// 1.首先找到ai-1的存储位置p,保存要删除的a的值
// 2.令p->next指向ai+1
Status ListDelete(LinkList &L, int i, ElemType &e)
{
LinkList p = L;
LinkList q;
int j = 0;
while (p->next && j < i-1) //寻找第i个结点,并令p指向其前驱
{
p = p->next;
++j;
}
if (!(p->next) || j > i-1) //删除位置不合理
return 0;
q = p->next; //临时保存被删结点的地址以备释放
p->next = q->next; //改变被删结点前驱结点指针域
e = q->data; //保存被删结点数据域
delete q; //释放结点空间
return 1;
}
//9.头插法建立链表
//算法步骤:
// 1.从一个空表开始,重复读入数据
// 2.生成新节点,将读入数据存放到新结点数据域中
// 3.从最后一个结点开始,依次将各结点插入链表前端
void CreatList_L(LinkList &L, int n)
{
LinkList p;
L = new LNode;
L->next = NULL; //先建立一个带头结点的单链表
for (int i = n; i > 0; --i)
{
p = new LNode; //生成新节点
cin >> p->data;
p->next = L->next; //插入到表头
L->next = p;
}
}
//10.尾插法建立链表
//算法步骤:
// 1.从一个空表L开始,将新结点逐个插入到链表的尾部,尾指针r指向链表的尾结点
// 2.初始时,r和L同时指向头结点,每读入一个数据新生成一个结点
// 将新结点插到尾结点后,r指向新结点
void CreatList_R(LinkList &L, int n)
{
LinkList r, p;
L = new LNode;
L->next = NULL;
r = L; //尾指针指向头结点
for (int i = 0; i < n; ++i)
{
p = new LNode;
cin >> p->data;
p->next = NULL;
r->next = p; //插入到表尾
r = p; //r指向新的尾结点
}
}
/*****************功能函数**************/
//遍历输出函数
void PrintList(LinkList L)
{
LinkList p = L->next; //跳过头结点
if(ListLength(L))
{
printf("当前单链表所有元素:");
while(p)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
else
{
printf("当前单链表已空!\n");
}
}
//建立链表函数
void Create(LinkList &L)
{
int n = 5;
printf("请输入链表的长度:");
scanf("%d",&n);
printf("请输入链表的数据:");
CreatList_R(L, n); //尾插
if( ListEmpty(L) )
{
printf("建表失败!!!\n");
}
else
{
printf("建表成功!!!\n");
// PrintList(L);
}
}
//插入功能函数,调用ListInsert函数
void Insert(LinkList &L)
{
int place;
ElemType e;
bool flag;
printf("请输入要插入的位置(从1开始)及元素:\n");
scanf("%d %d", &place, &e);
flag=ListInsert(L,place,e);
if(flag)
{
printf("插入成功!!!\n");
// PrintList(L);
}
}
//删除功能函数 调用ListDelete删除
void Delete(LinkList L)
{
int place, e;
bool flag;
printf("请输入要删除的位置(从1开始):\n");
scanf("%d",&place);
flag=ListDelete(L, place, e);
if(flag)
{
printf("删除成功!!!\n");
printf("删除的元素是 :%d\n", e);
// PrintList(L);
}
}
//查找函数
void Search(LinkList L)
{
ElemType e;
LNode *q;
printf("请输入要查找的值:\n");
scanf("%d",&e);
q=LocateElem(L,e);
if(q)
{
printf("找到该元素!\n");
}
else
printf("未找到该元素!\n");
}
void menu()
{
printf("********1.建表 2.输出*********\n");
printf("********3.插入 4.删除*********\n");
printf("********5.查找 6.退出*********\n");
}
int main()
{
LinkList L;
int choice;
InitList(L);
while(1)
{
menu();
printf("请输入菜单序号:\n");
scanf("%d",&choice);
if(choice==6) break;
switch(choice)
{
case 1:Create(L);break;
case 2:PrintList(L);break;
case 3:Insert(L);break;
case 4:Delete(L);break;
case 5:Search(L);break;
default:printf("输入错误!!!\n");
}
}
return 0;
}
数据结构——单链表算法及完整操作
最新推荐文章于 2023-05-07 21:40:08 发布