#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
using namespace std;
typedef struct LNode{ //定义单链表结点类型
int data; //数据域:每个结点存放一个数据元素
struct LNode *next; //指针域:指针指向下一个结点
}LNode, *LinkList;
//按位查找,返回第i个元素(带头结点)
LNode *GetElem(LinkList L, int i) //LinkList L可以换成LNode *L
{
if(i < 0)
return NULL;
LNode *p; //指针p用来指向当前扫描到的结点
int j = 0;
p = L;
while(p != NULL && j < i)
{
p = p->next;
j++;
}
return p; //返回一个指针
}
//按值查找,找到数据域为e的结点
LNode *LocateElem(LinkList L, int e, int &place) //用place返回位序!
{
int i = 1;
LNode *p = L->next; //从第一个结点开始查找数据域为e的结点
while(p != NULL && p->data != e)
{
p = p->next;
i++;
}
place = i;
return p; //返回一个指针
}
//求表的长度,头结点无数据,去除头结点
int ListLength(LinkList L)
{
int len = 0;
LNode *p = L;
while(p->next != NULL)
{
p = p->next;
len++;
}
return len - 1; //去除头结点
}
//初始化一个单链表(带头结点)
bool InitList(LinkList &L)
{
L = (LNode *)malloc(sizeof(LNode)); //创建并分配一个头结点
if(L == NULL)
return false; //内存不足,分配失败
L->next = NULL; //头结点后暂时还没有结点
return true;
}
//在第i个位置插入元素e(带头结点)
bool ListInsert(LinkList &L, int i, int e)
{
//以下代码等价于直接调用 LNode *p = GetElem(L, i - 1) //找到第i-1个结点,并用p指向它
if(i < 1)
return false;
LNode *p; //指针p指向当前扫描到的结点
int j = 0;
p = L;
while(p != NULL && j < i - 1) //找到插入位置的前驱结点
{
p = p->next;
j++;
}
//以下代码等价于直接调用 return InsertNextNode(p, e);
if(p == NULL) //i值不合法
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
//在第i个位置插入元素e(不带头结点)
bool ListInsert2(LinkList &L, int i, int e)
{
if(i < 1)
return false;
if(i == 1)
{
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = L;
L = s; //头指针指向新结点
}
LNode *p; //指针p指向当前扫描到的结点
int j = 0;
p = L;
while(p != NULL && j < i - 1) //找到插入位置的前驱结点
{
p = p->next;
j++;
}
if(p == NULL) //i值不合法
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
//后插操作:在p结点之后插入元素e
bool InsertNextNode(LNode *p, int e)
{
if(p == NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s == NULL) //内存分配失败
return false;
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
//前插操作:在p结点之前插入元素e
bool InsertPriorNode(LNode *p, int e)
{
if(p == NULL)
return false;
LNode *s = (LNode *)malloc(sizeof(LNode));
if(s == NULL)
return false; //内存分配失败
s->next = p->next;
p->next = s;
s->data = p->data;
p->data = e;
return true;
}
//(带头结点)删除表L中第i个位置的元素,并用e返回删除元素的值。
bool ListDelete(LinkList &L, int i, int &e)
{
LNode *p = GetElem(L, i - 1); //找到第i-1个结点,并用p指向它
if(p == NULL)
return false; //i值不合法
if(p->next == NULL)
return false; //第i-1个结点之后已无其他结点
LNode *q = p->next; //定义一个指针q,指向要删除的结点
e = q->data;
p->next = q->next; //将*q从链中断开
free(q);
return true;
}
//尾插法建立单链表
LinkList List_TailInsert(LinkList &L)
{
int x;
L = (LinkList)malloc(sizeof(LNode)); //建立头结点
L->next = NULL;
LNode *s,*r = L;
printf("请输入插入的值:\n"); //建立表尾指针
scanf("%d", &x);
while(x != 9999)
{
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
r->next = s;
r = s;
scanf("%d", &x);
}
r->next = NULL; //表尾指针后继置空
return L; //返回头结点L
}
//头插法建立单链表
LinkList List_HeadInsert(LinkList &L)
{
LNode *s;
int x;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
printf("请输入插入的值:\n");
scanf("%d", &x);
while(x != 9999)
{
s = (LNode *)malloc(sizeof(LNode));
s->data = x;
s->next = L->next;
L->next = s;
scanf("%d", &x);
}
return L;
}
//删除所有值为x的结点(带头结点)
void Del_X_3(LinkList &L)
{
int x;
LNode *p = L->next; //p用来遍历单链表
LNode *q; //q用来暂时替代p,然后将结点free
LNode * pre = L;
printf("请输入删除重复值:");
scanf("%d", &x);
while(p != NULL)
{
if(p->data == x)
{
q = p;
pre->next = q->next;
p = p->next;
free(q);
}
else
{
pre = p; //pre要一直为p的前驱
p = p->next;
}
}
}
//**************************************功能函数*********************************************
//遍历输出函数
void PrintList(LinkList L)
{
LNode *p = L->next; //跳过头结点
if(ListLength(L))
{
printf("当前单链表所有元素:\n");
while(p)
{
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
else
printf("当前单链表为空\n");
}
//插入功能函数
void Insert(LinkList &L)
{
int place, e;
bool flag;
printf("请输入要插入的位置(从1开始)及元素(空格隔开):\n");
scanf("%d %d", &place, &e);
flag = ListInsert(L, place, e);
if(flag)
{
printf("插入成功!\n");
PrintList(L);
}
}
//删除功能函数
void Delete(LinkList &L)
{
int place, e;
bool flag;
printf("请输入要删除的位置(从1开始):\n");
scanf("%d", &place);
flag = ListDelete(L, place, e);
if(flag)
{
printf("元素%d删除成功!\n", e);
PrintList(L);
}
}
//查找功能函数,调用LocateElem查找
void Search(LinkList L)
{
int e, place;
LNode *q;
printf("请输入想查找的值:");
scanf("%d", &e);
q = LocateElem(L, e, place);
if(q)
printf("找到该元素!在链表的第%d个位置!\n",place);//用place返回位序!
else
printf("未找到该元素!\n");
}
//从尾到头输出每个结点的值
void R_Print(LinkList L)
{
LNode *p = L->next, *r = NULL; //r用来限制每次遍历的长度
while(p->next != r)
{
p = p->next;
if(p->next == r)
{
printf("%d", p->data);
r = p;
p = L->next;
}
}
printf("%d", p->data); //输出第一个元素(头结点之后第一个结点)
}
//删除唯一最小值结点(带头结点)
void Delete_Min(LinkList &L)
{
LNode *p = L->next; //p用来遍历结点,与q作大小比较
LNode *q = p; //q指向当前最小结点
LNode *pre = L; //pre始终指向q的前驱结点
while(p->next != NULL)
{
if(q->data > p->next->data)
{
pre = p;
q = p->next;
}
p = p->next;
}
pre->next = q->next;
free(q);
}
//递增输出并释放空间
void Min_Delete(LinkList &L)
{
LNode *p = L->next;
LNode *pre = L; //指向q的前驱结点
LNode *q = p; //指向最小值的结点
while(p->next != NULL)
{
if(q->data > p->next->data)
{
q = p->next;
pre = p;
}
p = p->next;
}
printf("%d ",q->data);
pre->next = q->next;
free(q); //每次循环找到最小值结点并释放
}
//就地逆置(带头结点)
void Reverse(LinkList &L)
{
LNode *p = L->next; //p指向头结点后一个结点
LNode *r;
L->next = NULL;
while(p)
{
r = p->next;
p->next = L->next; //p结点指向头结点的后继
L->next = p;
p = r;
}
}
//删除结点元素值在(s,t)内的结点
void RangeDelete(LinkList &L)
{
int s, t;
LNode *p = L->next, *q;
LNode *pre = L;
printf("请输入(s,t)的值(空格隔开):");
scanf("%d %d", &s, &t);
while(p)
{
q = p; //q用来暂存p结点
p = p->next; //趁p还未改变时将p往后移动
if(q->data < t && q->data > s)
{
pre->next = q->next;
free(q);
}
else
pre = q; //不满足条件则将pre往后移
}
}
//递增排序(带头结点)
void Sort(LinkList &L)
{
LNode *p = L->next; //用来指向插入元素
LNode *r = p->next;
LNode *pre;
p->next = NULL;
p = r;
while(p)
{
r = p->next;
pre = L; //每次循环都让pre指向头结点
while(pre->next != NULL && pre->next->data < p->data)
pre = pre->next; //判断p插入的位置,并使pre指向插入位置的前驱结点
p->next = pre->next;
pre->next = p;
p = r;
}
}
void menu()
{
printf(" \n");
printf("1、 尾插\n");
printf("2、 头插\n");
printf("3、 插入\n");
printf("4、 删除\n");
printf("5、 删除重复元素\n");
printf("6、 按值查找\n");
printf("7、 输出\n");
printf("8、 逆序输出\n");
printf("9、 删除唯一最小值\n");
printf("10、就地逆置\n");
printf("11、递增排序\n");
printf("12、删除区间值\n");
printf("13、增序输出并释放空间\n");
printf("0、 退出\n");
}
int main()
{
LinkList L; //声明一个指向单链表的指针
int choice;
while(1)
{
menu();
printf("请输入菜单序号:\n");
scanf("%d", &choice);
if(choice == 0)
break;
switch(choice)
{
case 1:List_TailInsert(L);break;
case 2:List_HeadInsert(L);break;
case 3:Insert(L);break;
case 4:Delete(L);break;
case 5:Del_X_3(L);break;
case 6:Search(L);break;
case 7:PrintList(L);break;
case 8:R_Print(L);break;
case 9:Delete_Min(L);break;
case 10:Reverse(L);break;
case 11:Sort(L);break;
case 12:RangeDelete(L);break;
case 13:pjj(L);break;
default:printf("输入错误!\n");
}
}
return 0;
}
单链表的建立(源码)
于 2022-04-02 13:22:07 首次发布