单链表
用的是C语言不是C++,编译器vs2019,出现的 scanf_s() 在vs需要,如果复制到其他地方可以改成 scanf()
严蔚敏教材-算法2.6-2.12
单链表存储结构
//头文件
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
//宏定义
#define OK 1
#define ERROR -1
#define OVERFLOW -2
#define ElemType int
#define Status int
//结构体;
typedef struct LNode {
ElemType data;
struct LNode* next;
}LNode, * LinkList;
算法2.6:初始化
LinkList InitList(LinkList L) {
L = (LNode*)malloc(sizeof(LNode)); //生成新头结点作为头结点,用头指针L指向头结点
if (!L) {
printf("开辟空间错误");
return ERROR;
}
L->next = NULL; //头结点的指针域置空
return L;
}
算法2.7:单链表的取值
Status GetElem(LinkList L, int i, ElemType* e) {
LNode* p = L->next; int j = 1; //初始化,p 指向首元结点,计数器 j 初值赋为 1
while (p && j < i) { //顺链域向后扫描,直到p为空或者 p 指向第 i 个元素
p = p->next; // p 指向下一结点
++j; //计数器j相应加 1
}
if (!p || j > i) { //i 值不合法 i > n 或 i <= 0
printf("取值错误\n");
return ERROR;
}
*e = p->data; //取第 i 个结点的数据域
return OK;
}
算法2.8:单链表按值查找
LNode* LocateElem(LinkList L, ElemType e) {
LNode* p = L->next;
while (p && p->data != e) { //顺链域向后扫描,直到 p 为空或 p 所指结点的数据域等于 e
p = p->next; //p 指向下一结点
}
return p; //查找成功返回值为 e 的结点地址p ,查找失败 p 为 NULL
}
算法2.9:单链表的插入
LinkList ListInsert(LinkList L, int i, ElemType e) {
LNode* p = L;
int j = 0;
while (p && (j < i - 1)){
p = p->next;
++j;
}
if (!p || (j > i - 1)) {
printf("插入错误\n");
return ERROR;
}
LNode* s = (LNode*)malloc(sizeof(LNode));
if (!s) {
printf("开辟空间错误");
return ERROR;
}
s->data = e;
s->next = p->next;
p->next = s;
return L;
}
算法2.10:单链表的删除
//算法2.10:单链表的删除
LinkList ListDelete(LinkList L, int i) {
LNode* p = L;
int j = 0;
while ((p->next) && (j < i - 1)) {
p = p->next;
++j;
}
if (!(p->next) || (j > i - 1)) {
printf("单链表删除错误\n");
return ERROR;
}
LNode* q = p->next;
p->next = q->next;
free(q);
return L;
}
算法2.11:前插法创建单链表
LinkList CreateList_H(LinkList L, int n) {
L = (LNode*)malloc(sizeof(LNode));
if (!L) { //尾指针 r 指向头结点
printf("开辟空间错误");
return ERROR;
}
L->next = NULL;
for (int i = 0; i < n; i++) {
LNode* p = (LNode*)malloc(sizeof(LNode));
if (!p) { //尾指针 r 指向头结点
printf("开辟空间错误");
return ERROR;
}
printf("第 %d 位的元素为:", n - i);
scanf_s("%d", &(p)->data);
p->next = L->next;
L->next = p;
}
return L;
}
算法2.12:后插法创建单链表
LinkList CreateList_R(LinkList L, int n) {
L = (LNode*)malloc(sizeof(LNode)); //先建立一个带头结点的空链表
if (!L) { //尾指针 r 指向头结点
printf("开辟空间错误");
return ERROR;
}
L->next = NULL;
LNode* r = L;
printf("请输入插入的值(空格分开或回车%d次):\n",n);
for (int i = 0; i < n; ++i) {
LNode* p = (LNode*)malloc(sizeof(LNode)); //生成新结点
if (!p) {
printf("开辟空间错误");
return ERROR;
}
printf("第 %d 位的元素为:", i + 1);
scanf_s("%d", &(p)->data); //输入元素值赋给新结点 *p 的数据域(根据需要自由修改)
p->next = NULL; //将新结点 *p 插入尾结点 *r 后
r->next = p;
r = p; //r 指向新的尾结点 *p
}
return L;
}
自制-辅助算法:遍历表并输出
//自制-辅助算法:遍历表并输出
Status GetList(LinkList L) {
LNode* p = L->next;
printf("当前表内元素为:");
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
return OK;
}
测试链表程序
//头文件
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <malloc.h>
//宏定义
#define OK 1
#define ERROR -1
#define OVERFLOW -2
#define ElemType int
#define Status int
//结构体;
typedef struct LNode {
ElemType data;
struct LNode* next;
}LNode, * LinkList;
//函数声明
LinkList InitList(LinkList L);
LinkList CreateList_R(LinkList L, int n);
Status GetList(LinkList L);
Status GetElem(LinkList L, int i, ElemType* e);
LNode* LocateElem(LinkList L, ElemType e);
LinkList ListInsert(LinkList L, int i, ElemType e);
LinkList ListDelete(LinkList L, int i);
LinkList CreateList_H(LinkList L, int n);
int main(void) {
LinkList L;
int n = 0;
int i = 0;
L = InitList(&L);
//输入长度 n ,后插法插入元素
printf("请输入链表长度n:");
scanf_s("%d", &n);
//自由选择头插或尾插
L = CreateList_R(&L, n); //尾插法
//L = CreateList_H(&L, n); //头插法
GetList(L); //遍历函数内容并输出
//指定位置 i,取表内元素
ElemType E, * e = &E;
printf("请输入取值的位置i:");
scanf_s("%d", &i);
i = GetElem(L, i, e);
if(i != ERROR)
printf("第 %d 的元素为:%d\n", i, *e);
//输入元素 *e,查找表内元素
printf("请输入查找的值*e:");
scanf_s("%d", e);
LNode* p = LocateElem(L, *e);
if (p == NULL)
printf("未找到为 %d 的值\n",*e);
else
printf("找到的元素为:%d\n", p->data);
//单链表的插入 e 到位置 i
printf("请输入插入的位置i:");
scanf_s("%d",&i);
printf("请输入插入的元素*e:");
scanf_s("%d", e);
L = ListInsert(L, i, *e);
if(L != ERROR)
GetList(L);
//单链表删除位置 i 的元素
printf("请输入删除的位置i:");
scanf_s("%d", &i);
L = ListDelete(L, i);
if (L != ERROR)
GetList(L);
system("pause");
return 0;
}
//算法2.6:初始化
LinkList InitList(LinkList L) {
L = (LNode*)malloc(sizeof(LNode)); //生成新头结点作为头结点,用头指针L指向头结点
if (!L) {
printf("开辟空间错误");
return ERROR;
}
L->next = NULL; //头结点的指针域置空
return L;
}
//算法2.7:单链表的取值
Status GetElem(LinkList L, int i, ElemType* e) {
LNode* p = L->next; int j = 1; //初始化,p 指向首元结点,计数器 j 初值赋为 1
while (p && j < i) { //顺链域向后扫描,直到p为空或者 p 指向第 i 个元素
p = p->next; // p 指向下一结点
++j; //计数器j相应加 1
}
if (!p || j > i) { //i 值不合法 i > n 或 i <= 0
printf("取值错误\n");
return ERROR;
}
*e = p->data; //取第 i 个结点的数据域
return OK;
}
//算法2.8:单链表按值查找
LNode* LocateElem(LinkList L, ElemType e) {
LNode* p = L->next;
while (p && p->data != e) { //顺链域向后扫描,直到 p 为空或 p 所指结点的数据域等于 e
p = p->next; //p 指向下一结点
}
return p; //查找成功返回值为 e 的结点地址p ,查找失败 p 为 NULL
}
//算法2.9:单链表的插入
LinkList ListInsert(LinkList L, int i, ElemType e) {
LNode* p = L;
int j = 0;
while (p && (j < i - 1)){
p = p->next;
++j;
}
if (!p || (j > i - 1)) {
printf("插入错误\n");
return ERROR;
}
LNode* s = (LNode*)malloc(sizeof(LNode));
if (!s) {
printf("开辟空间错误");
return ERROR;
}
s->data = e;
s->next = p->next;
p->next = s;
return L;
}
//算法2.10:单链表的删除
LinkList ListDelete(LinkList L, int i) {
LNode* p = L;
int j = 0;
while ((p->next) && (j < i - 1)) {
p = p->next;
++j;
}
if (!(p->next) || (j > i - 1)) {
printf("单链表删除错误\n");
return ERROR;
}
LNode* q = p->next;
p->next = q->next;
free(q);
return L;
}
//算法2.11:前插法创建单链表
LinkList CreateList_H(LinkList L, int n) {
L = (LNode*)malloc(sizeof(LNode));
if (!L) { //尾指针 r 指向头结点
printf("开辟空间错误");
return ERROR;
}
L->next = NULL;
for (int i = 0; i < n; i++) {
LNode* p = (LNode*)malloc(sizeof(LNode));
if (!p) { //尾指针 r 指向头结点
printf("开辟空间错误");
return ERROR;
}
printf("第 %d 位的元素为:", n - i);
scanf_s("%d", &(p)->data);
p->next = L->next;
L->next = p;
}
return L;
}
//算法2.12:后插法创建单链表
LinkList CreateList_R(LinkList L, int n) {
L = (LNode*)malloc(sizeof(LNode)); //先建立一个带头结点的空链表
if (!L) { //尾指针 r 指向头结点
printf("开辟空间错误");
return ERROR;
}
L->next = NULL;
LNode* r = L;
printf("请输入插入的值(空格分开或回车%d次):\n",n);
for (int i = 0; i < n; ++i) {
LNode* p = (LNode*)malloc(sizeof(LNode)); //生成新结点
if (!p) {
printf("开辟空间错误");
return ERROR;
}
printf("第 %d 位的元素为:", i + 1);
scanf_s("%d", &(p)->data); //输入元素值赋给新结点 *p 的数据域
p->next = NULL; //将新结点 *p 插入尾结点 *r 后
r->next = p;
r = p; //r 指向新的尾结点 *p
}
return L;
}
//自制-辅助算法:遍历表并输出
Status GetList(LinkList L) {
LNode* p = L->next;
printf("当前表内元素为:");
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
return OK;
}