单链表-严蔚敏教材-C语言实现

单链表

用的是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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值