#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <stdlib.h> // 添加头文件以使用malloc和free函数
#define ERROR 0
#define OK 1
typedef int Status;//判断程序是否运行成功 0-失败 1-成功
typedef int Element;
typedef struct Node{
Element data;
struct Node* next;//结构体中不可以直接使用Node名字声明
}Node,LinkList;
//LinkList存储头地址
//初始化链表
Status initiList(LinkList *L) {
L = (Node*)malloc(sizeof(Node));
if (L == NULL) {
exit;//申请内存失败
}
L->next = NULL;
return OK;//申请内存成功
}
//获取元素功能,获取元素并返回给e变量
Status getList(LinkList *L, int i, Element e) {
int j=1;//计数器,来计算遍历的位置
LinkList* p;//声明一个指针来指向头结点
p = L->next;//绕过头节点
while (p && j < i) {//判断指针是否为空,为空就是空表,注:i与j判断之间不可以取等号,因为第i个位置的地址是在前一个结点的后继指针
p = p->next;
j++;
}
if (!p || j > i)return ERROR;//j>i,避免i<1时造成查找错误
e = p->data;
}
//链表的插入
/*
* 两种种情况
* 1.插中间
* 2.插末尾
*/
Status insertList(LinkList* L, int i, Element e) {
LinkList *p=L;
int j = 1;//计数从零开始计数
//插中间
while (p && j < i) {//遍历到插入位置的前一个地方
p = p->next;
j++;
}
if (!p || j > i) {
return ERROR;
}
Node* s = (Node*)malloc(sizeof(Node));
/*
* 插入时需要注意先接后面,再接前面;若先接前面,后面部分就会丢失找不到
*/
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
//查找元素
Node* findList(LinkList *L, Element e) {
Node* p = L->next;
while (p != NULL && p->data != e) {
p = p->next;
}
return p;//若在遍历玩之前查到,返回该元素所在地址,若未查到返回NULL;
}
//删除单链表某一节点
Status deleteElem(LinkList *L, int i) {//此时的i指的是第i个元素,不包括头节点
int j = 1;//计数器
LinkList *p;//存储头结点
p = L;
/*
* 由于不包括头结点,所以需要判断p->next是否为空(这里与插入功能需要区别开)
*/
while (p->next && j < i) {
p = p->next;
j++;
}
if (p->next != NULL || j > i) {
return ERROR;
}
LinkList *q = p->next;//删除第i个元素,但地址实际存储在i-1位置,所有释放的是p->next所指向的内存
p->next = q->next;
free(q);
return OK;//删除成功
/*
* 插入功能while(p&&j<i)与删除功能while(p->next&&j<i)判断条件的理解(i代表的是元素的位置,不包括头结点)
* 1.插入功能中只需要判断到第i-1位位置不是空,就可以直接插入元素
* 2.删除功能则需要判断第i-1位的下一个元素不能为空,因为删除的目的就是释放那个位置内存,则需要判断i-1指的下一个结点(即next)
* 不能为空,要不然删除毫无意义
*/
}
//删除全部元素
Status deleteAll(LinkList *L) {
LinkList* p=L->next;
LinkList* q;
while (p) {
q = p->next;
free(p);
p = q;
}
L->next = NULL;
return OK;
}
//单链表的整表建立(使用随机数建立)
//1.头插法,顾名思义一直插在头后面
void creatList1(LinkList *L, int n) {
LinkList *p;
srand(time(0));//创建随机数
for (int i = 0; i < n; i++) {
p = (Node*)malloc(sizeof(Node));
p->data = rand() % 100 + 1;
p->next = L->next;
L->next = p;
}
}
//2.尾插法,类似于排队,一直后插
void creatList2(LinkList *L, int n) {
LinkList *p,*r;
r = L;
srand(time(0));
for (int i = 0; i < n; i++) {
p = (Node*)malloc(sizeof(Node));
p->data = rand() % 100 + 1;
r->next = p;
r = p;
}
r->next = NULL;
}
//遍历链表
void searchList(LinkList L) {
LinkList * p = L.next;
/*for (int i = 0; i < 20; i++) {
printf("%d\n", p->data);
p = p->next;
}*/
while (p != NULL) {
printf("%d\n", p->data);
p = p->next;
}
return OK;
}
int main() {
LinkList L;//存储头元素
int choice=0;
int index=0;
Element elem=0;
while(OK) {
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");
scanf("%d", &choice);
switch(choice) {
case 1:
initiList(&L),
printf("Successful initialization!\n");
break;
case 2:
creatList1(&L, 20);
printf("Creat List successfully!\n");
break;
case 3:
creatList2(&L, 20);
printf("Creat List successfully!\n");
break;
case 4:
printf("输入要删除元素的位置\n");
scanf("%d", &index);
deleteElem( &L, index);
printf("删除成功!");
break;
case 5:
deleteAll(&L);
printf("删除成功");
break;
case 6:
printf("输入你想查找的元素(整数)\n");
scanf("%d", &elem);
Element* e = findList(&L, elem);
printf("你所查找的元素地址为%p", e);
break;
case 7:
printf("请输入你想插入的指的位置\n");
scanf("%d", &index);
printf("请输入你想插入的元素\n");
scanf("%d", &elem);
insertList(&L, index, elem);
printf("insert successfully!\n");
break;
case 8:
searchList(L);
break;
case 9:
printf("请输入获取位置的元素\n");
scanf("%d", &index);
getList(&L, index, elem);
printf("该位置元素为:%d", elem);
break;
case 10:
return 0;
default:
break;
}
}
}
我这个遍历功能为什么错了