#include <iostream>
#include <stdlib.h>
#include <windows.h>
//定义单链表的结构体存储数据类型
typedef struct LNode{
int elem;
struct LNode *next;//指针域
}LNode,*LinkedList;
//定义逆向创建并初始化单链表函数
void reverseCreateList(LinkedList &L,int n){//n为初始化单链表的填充数据个数
L = (LinkedList)malloc(sizeof(LNode));
L->next = NULL;//初始化头结点
for(int i=n;i>0;i--){
LNode *p = (LNode*)malloc(sizeof(LNode));//生成新结点
printf("请输入第%d个结点的值:",i);
scanf("%d",&p->elem);
p->next = L->next;
L->next = p;//新结点插入到表头
}
}
//定义正序创建并初始化单链表函数
void positiveCreateList(LinkedList &L,int n){
L = (LinkedList)malloc(sizeof(LNode));
L->next = NULL;
LNode *rear = L;//定义一个尾指针指向头指针L
for(int i=0;i<n;i++){
LNode *p = (LNode*)malloc(sizeof(LNode));//生成新结点
printf("请输入第%d个结点的值:",i+1);
scanf("%d",&p->elem);
p->next = NULL;//指针p的next域置为NULL
rear->next = p;//rear指针指向当前单链表的末尾结点,此操作修改末尾结点的指针域,使其指向新结点,建立联系
rear = p;//将新结点加入单链表后,末尾结点则为新结点,改变尾指针指向
}
}
//定义遍历单链表函数
void traverseList(LinkedList L){
LNode *p = L->next;//指针p指向首元结点
int i = 0;//i用于表示结点的位置
printf("==================\n");
while(p != NULL){
i++;
printf("第%d个结点的值:%d\n",i,p->elem);
p = p->next;//指针p指向下一结点
}
printf("==================\n");
}
//定义单链表取指定位置数据元素值函数
bool getValue(LinkedList L,int i,int &e){
LNode *p = L->next;
int j = 1;//j变量用于计数器
while(p != NULL && j<i){
p = p->next;
j++;
}
if(p == NULL || j>i){//当i值为0时,出现j>i;当i>单链表表长时出现p为空
return false;
}
e = p->elem;
return true;
}
//定义单链表插入数据元素函数
bool insertElemList(LinkedList &L,int i,int e){//之所以使用&L,是因为当i为1时,需改变头指针指向
LNode *p = L;
int j = 0;
while(p !=NULL && j<i-1){
p = p->next;
j++;
}//使p指针指向插入位置i的前驱结点
if(p == NULL || j>i-1){//当i为0时,出现j>i-1;当i>单链表表长+1时,出现p为NULL
return false;
}
LNode *q = (LNode*)malloc(sizeof(LNode));//生成新结点
q->elem = e;
q->next = p->next;
p->next = q;//顺序不可颠倒
return true;
}
//定义单链表删除数据元素函数
bool deleteElemList(LinkedList &L,int i,int &e){
LNode *p = L;
int j = 0;
while(p->next != NULL && j<i-1){//之所以使用p->next而不是用p,是为了检测将要删除的位置i的结点是否为空,
//如果此处使用p,则会导致下面q->next语法错误
p = p->next;
j++;
}
if(p->next == NULL || j>i-1){
return false;
}
LNode *q = p->next;//定义指针q指向将要被删除结点
p->next = q->next;
e = q->elem;
free(q);//释放q所指的内存空间
return true;
}
//定义单链表查询指定数据所在结点位置函数
int inquireValue(LinkedList L,int e){
LNode *p = L->next;//p指针指向单链表的首元结点
int j = 1;//j为计数器
while(p != NULL){
if(p->elem == e){
return j;
}else{
p = p->next;
j++;
}
}
return 0;//返回值0表示没找到e
}
//定义打印单链表功能菜单函数
void functionMenu(void){
char *menu[] = {
"1_逆向创建并初始化单链表操作","2_正序创建并初始化单链表操作",
"3_遍历单链表操作","4_单链表取指定位置数据元素值操作",
"5_单链表插入数据元素操作","6_单链表删除数据元素操作",
"7_单链表查询指定数据所在结点位置操作"
};
printf("================================\n");
for(int i=0;i<sizeof(menu)/sizeof(char*);i++){
printf("%s\n",menu[i]);
}
printf("================================\n");
}
//定义单链表操作函数
void operateList(LinkedList &L){
int funNo = 0;//功能编号
int n = 0;//创建单链表初始填入的数据个数
int e = 0;//接收删除数据元素值或查询的数值
int i = 0;//插入或删除的位置
bool flag = true;
while(flag){
functionMenu( );
printf("请输入将要执行操作对应的功能编号:");
scanf("%d",&funNo);
switch(funNo){
case 1:
printf("请输入初始填充的数据个数n:");
scanf("%d",&n);
reverseCreateList(L,n);
break;
case 2:
printf("请输入初始填充的数据个数n:");
scanf("%d",&n);
positiveCreateList(L,n);
break;
case 3:
traverseList(L);
break;
case 4:
printf("请输入取值位置i:");
scanf("%d",&i);
if(getValue(L,i,e)){
printf("第%d个结点的值:%d\n",i,e);
}else{
printf("取值操作失败\n");
}
break;
case 5:
printf("请输入插入数据元素的位置i:");
scanf("%d",&i);
printf("请输入插入的数值e:");
scanf("%d",&e);
if(insertElemList(L,i,e)){
printf("插入数据元素操作成功\n");
}else{
printf("插入数据元素操作失败\n");
}
break;
case 6:
printf("请输入删除数据元素的位置i:");
scanf("%d",&i);
if(deleteElemList(L,i,e)){
printf("删除数据元素%d操作成功\n",e);
}else{
printf("删除数据元素操作失败\n");
}
break;
case 7:
printf("请输入查询的数值e:");
scanf("%d",&e);
i= inquireValue(L,e);
if(i != 0){
printf("数值e:%d在单链表的第%d个结点处\n",e,i);
}else{
printf("没有查询到e\n");
}
break;
default:
printf("输入的funNo错误\n");
break;
}
printf("是否继续执行其他操作? 1-是 0-否:");
std::cin>>flag;
system("cls");//清屏
}
}
int main(void){
LinkedList L = NULL;//定义头指针L
operateList(L);
system("pause");
return 0;
}
[注意:函数之间的顺序不可以颠倒,我没有在一些函数中加上其调用函数的声明,如果改变顺序的话,可能会报错]
//如有不足,畅所欲言,谢谢点评