(四)第 2 章 线性表 (线性表的单链表存储)

1. 背景说明

 

2. 示例代码 

1) errorRecord.h

// 记录错误宏定义头文件

#ifndef ERROR_RECORD_H
#define ERROR_RECORD_H

#include <stdio.h>
#include <string.h>
#include <stdint.h>

// Extracts the file name from the file path
#define FILE_NAME(X) strrchr(X, '\\') ? strrchr(X, '\\') + 1 : X

// Define DEBUG macro for enabling debug mode
#define DEBUG

// Print error message
#ifdef DEBUG
#define ERR_RECORD(ERR_CODE, ...) do { \
    printf(ANSI_COLOR_BRIGHT_CYAN \
        "\n\nFile: %-25s Func: %-20s Line: %-10d ErrorCode: %-8d ErrorInfo: ", \
        FILE_NAME(__FILE__), __func__, __LINE__, (ERR_CODE)); \
    printf(""__VA_ARGS__); \
    printf("\n" ANSI_COLOR_RESET); \
    PrintErrorCodeInfo(ERR_CODE); \
} while (0)
#else
#define ERR_RECORD(ERR_CODE, FORMAT, ...)
#endif

// Function result status codes
enum StatusCode {
	RET_OK = 0,                 // Operation successful
	ERR_NULL_PTR = 1,           // Null pointer error
	ERR_MEMORY_ALLOCATE = 2,    // Memory allocation error
	ERR_EMPTY_STACK = 3,        // Empty stack error
	ERR_FULL_STACK = 4,			// Full stack error
	ERR_EMPTY_QUEUE = 5,        // Empty queue error
	ERR_FULL_QUEUE = 6,         // Full queue error
	ERR_PARA_ILLEGAL = 7,       // Parameter illegal error
	ERR_OPEN_FILE = 8,          // File open error
	ERR_NOT_EXIST = 9,          // Not exist error
};

enum BoolCode {
	TRUE = 1,
	FALSE = 0
};

typedef uint32_t Status;
typedef uint8_t Boolean;

// ANSI 转义码定义
#define ANSI_COLOR_BRIGHT_RED     "\x1b[91m"
#define ANSI_COLOR_BRIGHT_YELLOW  "\x1b[93m"
#define ANSI_COLOR_BRIGHT_CYAN    "\x1b[96m"
#define ANSI_COLOR_RESET          "\x1b[0m"

// Function to print error code information with bright colors
static void PrintErrorCodeInfo(int errorCode)
{
	switch (errorCode) {
		case ERR_NULL_PTR:
			printf(ANSI_COLOR_BRIGHT_RED "Null Pointer Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_MEMORY_ALLOCATE:
			printf(ANSI_COLOR_BRIGHT_RED "Memory Allocation Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_EMPTY_STACK:
			printf(ANSI_COLOR_BRIGHT_RED "Empty Stack Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_FULL_STACK:
			printf(ANSI_COLOR_BRIGHT_RED "Full Stack Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_EMPTY_QUEUE:
			printf(ANSI_COLOR_BRIGHT_RED "Empty Queue Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_FULL_QUEUE:
			printf(ANSI_COLOR_BRIGHT_RED "Full Queue Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_PARA_ILLEGAL:
			printf(ANSI_COLOR_BRIGHT_RED "Illegal Parameter Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_OPEN_FILE:
			printf(ANSI_COLOR_BRIGHT_RED "File Open Error\n\n" ANSI_COLOR_RESET);
			break;

		case ERR_NOT_EXIST:
			printf(ANSI_COLOR_BRIGHT_RED "Not Exist Error\n\n" ANSI_COLOR_RESET);
			break;

		default:
			printf(ANSI_COLOR_BRIGHT_YELLOW "Unknown Error Code: %d\n\n" ANSI_COLOR_RESET,
				errorCode);
			break;
	}
}

#endif // !ERROR_RECORD_H

2) singleLinkList.h

// 线性表的单链表存储结构头文件

#ifndef SINGLELINKLIST_H
#define SINGLELINKLIST_H

#include "errorRecord.h"

typedef int ElemType;

typedef struct LNode {
	ElemType data;
	struct LNode *next;
} *LinkList;

LinkList MakeNewLNode(ElemType e);

Status InitList(LinkList *list);

Status DestroyList(LinkList *list);

Status ClearList(LinkList list);

Status ListEmpty(LinkList list, Boolean *isEmpty);

Status ListLength(LinkList list, int *length);

Status GetElem(LinkList list, int i, ElemType *e);

Status LocateElem(LinkList list, ElemType e, Boolean(*compare)(ElemType, ElemType),
	int *pos);

Status PriorElem(LinkList list, ElemType cur_e, Boolean(*equal)(ElemType, ElemType),
	ElemType *pre_e);

Status NextElem(LinkList list, ElemType cur_e, Boolean(*equal)(ElemType, ElemType),
	ElemType *next_e);

Status ListInsert(int i, ElemType e, LinkList list);

Status ListDelete(int i, LinkList list, ElemType *e);

Status ListTraverse(LinkList list, void(*vi)(ElemType));

Status InsertAscend(ElemType e, int(*compare)(ElemType, ElemType),
	LinkList list);

Status InsertDescend(ElemType e, int(*compare)(ElemType, ElemType),
	LinkList list);

Status HeadInsert(ElemType e, LinkList list);

Status EndInsert(ElemType e, LinkList list);

Status DeleteFirst(LinkList list, ElemType *e);

Status DeleteTail(LinkList list, ElemType *e);

Status DeleteElem(ElemType e, Boolean(*compare)(ElemType, ElemType),
	LinkList list);

Status RePlaceElem(int i, ElemType e, LinkList list);

Status CreateSingleLinkList(int n, int(*compare)(ElemType, ElemType),
	Boolean isAscend, LinkList *list);

Status GetFirstElem(LinkList list, ElemType *e);

#endif

3) singleLinkList.c

// 线性表的单链表(带头结点)存储结构源文件实现

#include "singleLinkList.h"
#include <stdlib.h>

/*
	前置条件:无
	操作结果:辅助函数,创建一个新的结点
*/
LinkList MakeNewLNode(ElemType e)
{
	// 申请一个结点的内存空间并检查是否申请成功 
	LinkList newLNode = (LinkList)malloc(sizeof(struct LNode));
	if (!newLNode) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		return NULL;
	}

	// 为申请的结点赋值 
	newLNode->data = e;
	newLNode->next = NULL;

	return newLNode;
}

/*
	前置条件:list 非空
	操作结果:构造一个空的线性表 *list
*/
Status InitList(LinkList *list)
{
	if (!list) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	// 为头结点申请内存空间并检查是否申请成功 
	*list = (LinkList)malloc(sizeof(struct LNode));
	if (!(*list)) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	// 头结点数据域不赋值,next 指针赋值为空 
	(*list)->next = NULL;

	return RET_OK;
}

/*
	前置条件:线性表 *list 已存在
	操作结果:销毁线性表 *list
*/
Status DestroyList(LinkList *list)
{
	if (!list) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	LinkList p;
	while (*list) {
		p = (*list)->next;
		free(*list);
		*list = p;
	}

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在
	操作结果:将 list 重置为空表
*/
Status ClearList(LinkList list)
{
	if (!list) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	// 释放除头结点之外的其他结点 
	LinkList p, q;
	p = list->next;
	while (p) {
		q = p->next;
		free(p);
		p = q;
	}

	list->next = NULL;

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在
	操作结果:若 list 为空表,则用 *isEmpty 返回 TRUE,否则用 *isEmpty 返回 FALSE
*/
Status ListEmpty(LinkList list, Boolean *isEmpty)
{
	if (!list || !isEmpty) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, isEmpty = %p", list, isEmpty);
		return ERR_NULL_PTR;
	}

	*isEmpty = (list->next == NULL) ? TRUE : FALSE;

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在
	操作结果:用 *length 返回 list 中数据元素个数
*/
Status ListLength(LinkList list, int *length)
{
	if (!list || !length) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, length = %p", list, length);
		return ERR_NULL_PTR;
	}

	// 指针初始时指向线性表的第一个元素所在位置 
	*length = 0;
	LinkList p = list->next;
	while (p) {
		++(*length);
		p = p->next;
	}

	return RET_OK;
}

/*
	算法 2.8
	前置条件:list 为带头结点的单链表的头指针
	操作结果:当第 i 个元素存在时, 其值赋给 *e
*/
Status GetElem(LinkList list, int i, ElemType *e)
{
	if (!list || !e) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, e = %p", list, e);
		return ERR_NULL_PTR;
	}

	// 指针初始时指向线性表的第一个元素所在位置 
	int j = 1;
	LinkList p = list->next;
	while (p && (j < i)) {
		p = p->next;
		++j;
	}

	// j > i 适用于 i < 1 时,如 i = 0 
	if (!p || (j > i)) {
		ERR_RECORD(ERR_NOT_EXIST, "p = %p, j = %d, i = %d", p, j, i);
		return ERR_NOT_EXIST;
	}

	*e = p->data;

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在, compare() 是数据元素判定函数(满足为 1,否则为 0)
	操作结果:用 *pos 返回 list 中第 1 个与 e 满足关系 compare() 的数据元素的位序
*/
Status LocateElem(LinkList list, ElemType e, Boolean(*compare)(ElemType, ElemType),
	int *pos)
{
	if (!list || !compare || !pos) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, compare = %p, post = %p",
			list, compare, pos);
		return ERR_NULL_PTR;
	}

	// 指针初始时指向线性表的第一个元素所在位置 
	int i = 1;
	LinkList p = list->next;
	while (p) {
		if (compare(p->data, e)) {
			*pos = i;
			return RET_OK;
		}

		p = p->next;
		++i;
	}

	*pos = 0;
	ERR_RECORD(ERR_NOT_EXIST);

	return ERR_NOT_EXIST;
}

/*
	前置条件:线性表 list 已存在
	操作结果:若 cur_e 是 list 的数据元素,且不是第一个,则用 *pre_e 返回它的前驱
*/
Status PriorElem(LinkList list, ElemType cur_e, Boolean(*equal)(ElemType, ElemType),
	ElemType *pre_e)
{
	if (!list || !equal || !pre_e) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, equal = %p, pre_e = %p",
			list, equal, pre_e);
		return ERR_NULL_PTR;
	}

	// 指针 p 指向线性表的第 1 个元素 
	LinkList p = list->next;

	// 检查线性表是否存在第 1 个元素 
	if (!p) {
		ERR_RECORD(ERR_NOT_EXIST);
		return ERR_NOT_EXIST;
	}

	// 从第 2 个元素开始循环,校验当前元素是否为指定元素,如果是,则前
	// 一个元素为目标元素 
	while (p->next) {
		if (equal(p->next->data, cur_e)) {
			*pre_e = p->data;
			return RET_OK;
		}

		p = p->next;
	}

	ERR_RECORD(ERR_NOT_EXIST);

	return ERR_NOT_EXIST;
}

/*
	前置条件:线性表 list 已存在
	操作结果:若 cur_e 是 list 的数据元素,且不是最后一个,则用 next_e 返回它的后继
*/
Status NextElem(LinkList list, ElemType cur_e, Boolean(*equal)(ElemType, ElemType),
	ElemType *next_e)
{
	if (!list || !equal || !next_e) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, equal = %p, next_e = %p",
			list, equal, next_e);
		return ERR_NULL_PTR;
	}

	// 指针 p 指向线性表的第 1 个元素 
	LinkList p = list->next;

	// 检查线性表是否存在第 1 个元素 
	if (!p) {
		ERR_RECORD(ERR_NOT_EXIST);
		return ERR_NOT_EXIST;
	}

	// 从第 2 个元素开始循环,校验前一个元素是否为指定元素,如果是,则当
	// 前元素为目标元素 
	while (p->next) {
		if (equal(p->data, cur_e)) {
			*next_e = p->next->data;
			return RET_OK;
		}

		p = p->next;
	}

	ERR_RECORD(ERR_NOT_EXIST);

	return ERR_NOT_EXIST;
}

/*
	算法 2.9
	前置条件:线性表 list 已存在
	操作结果:在带头结点的单链线性表 list 中第 i 个位置之前插入元素 e
*/
Status ListInsert(int i, ElemType e, LinkList list)
{
	if (!list) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	// 在第 i 个位置之前插入元素,需要将指针移动 i - 1 个位置,以将指针
	// 置于第 i 个位置之前的位置 
	int j = 0;
	while (list && (j < i - 1)) {
		++j;
		list = list->next;
	}

	// 若 list 为空指针,说明 i 的值大于 list (已存在元素数量 + 1)
	// 若 (j > i - 1),说明 i 的值小于 1,注意与判断顺序无关,
	// 逻辑运算符 || 具有交换律 
	if (!list || (j > i - 1)) {
		ERR_RECORD(ERR_PARA_ILLEGAL, "list = %p, j = %d, i = %d",
			list, j, i);
		return ERR_PARA_ILLEGAL;
	}

	// 创造新的结点 
	LinkList newLNode = MakeNewLNode(e);
	if (!newLNode) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	// 插入新结点 
	newLNode->next = list->next;
	list->next = newLNode;

	return RET_OK;
}

/*
	算法 2.10
	前置条件:线性表 list 已存在
	操作结果:在带头结点的单链线性表 list 中,删除第 i 个元素,并由 *e 返回其值
*/
Status ListDelete(int i, LinkList list, ElemType *e)
{
	if (!list || !e) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, e = %p", list, e);
		return ERR_NULL_PTR;
	}

	// list->next 为 list 第一个元素的位置,移动 i - 1 个位置后,list 为
	// 第 i - 1 个元素的位置,list->next 为第 i 个元素的位置 
	int j = 0;
	while ((list->next) && (j < i - 1)) {
		++j;
		list = list->next;
	}

	// 如果 list->next 为空指针,说明不存在第 i 个元素,如果 (j > i - 1),
	// 说明 i 的值小于 1,注意与判断顺序无关,逻辑运算符 || 具有交换律 
	if (!(list->next) || (j > i - 1)) {
		ERR_RECORD(ERR_NOT_EXIST, "list->next = %p, j = %d, i - 1 = %d",
			list->next, j, i - 1);
		return ERR_NOT_EXIST;
	}

	// 删除第 i 个元素 
	LinkList p = list->next;
	*e = p->data;
	list->next = p->next;
	free(p);

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在
	操作结果:依次对 list 的每个数据元素调用函数 vi()。一旦 vi() 失败,则操作失败
*/
Status ListTraverse(LinkList list, void(*vi)(ElemType))
{
	if (!list || !vi) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, vi = %p", list, vi);
		return ERR_NULL_PTR;
	}

	// 从线性表的第 1 个元素开始遍历,不改变线性表中元素的值 
	while (list->next) {
		vi(list->next->data);
		list = list->next;
	}

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在
	操作结果:按照升序或者降序获取元素插入位置
*/
static LinkList GetInsertPos(LinkList list, ElemType e, Boolean isAscend,
	int(*compare)(ElemType, ElemType))
{
	// 初始时 q, p 分别指向线性表的头结点和第 1 个元素所在位置 
	LinkList q = list, p = list->next;

	// 如果按照升序插入,则如果当前元素存在且 e 大于当前元素值,则向后遍历,
	// 直到线性表 p 指向结点之后的结点的元素值均不小于 e 或 p 为空,此时 q 指向
	// 的位置为待插入元素的前 1 个位置 
	if (isAscend) {
		while ((p) && (compare(e, p->data) > 0)) {
			q = p;
			p = p->next;
		}

		return q;
	}

	// 如果按照降序插入,则如果当前元素存在且 e 小于当前元素值,则向后遍历,
	// 直到线性表 p 指向结点之后的结点的元素值均不大于 e 或 p 为空,此时 q 指向
	// 的位置为待插入元素的前 1 个位置 
	while ((p) && (compare(e, p->data) < 0)) {
		q = p;
		p = p->next;
	}

	return q;
}

/*
	前置条件:按非降序排列的线性表 list 已存在
	操作结果:在 list 中按非降序插入新的数据元素 e
*/
Status InsertAscend(ElemType e, int(*compare)(ElemType, ElemType),
	LinkList list)
{
	if (!compare || !list) {
		ERR_RECORD(ERR_NULL_PTR, "compare = %p, list = %p", compare, list);
		return ERR_NULL_PTR;
	}

	// 获取插入位置及创建新结点 
	LinkList q = GetInsertPos(list, e, TRUE, compare);
	LinkList newLNode = MakeNewLNode(e);
	if (!newLNode) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	// 插入新元素 
	LinkList p = q->next;
	q->next = newLNode;
	newLNode->next = p;

	return RET_OK;
}

/*
	前置条件:按非升序排列的线性表 list 已存在
	操作结果:在 list 中按非升序插入新的数据元素 e
*/
Status InsertDescend(ElemType e, int(*compare)(ElemType, ElemType),
	LinkList list)
{
	if (!compare || !list) {
		ERR_RECORD(ERR_NULL_PTR, "compare = %p, list = %p", compare, list);
		return ERR_NULL_PTR;
	}

	// 获取插入位置及创建新结点 
	LinkList q = GetInsertPos(list, e, FALSE, compare);
	LinkList newLNode = MakeNewLNode(e);
	if (!newLNode) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	// 插入新元素 
	LinkList p = q->next;
	q->next = newLNode;
	newLNode->next = p;

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在
	操作结果:在 list 的头部插入新的数据元素 e, 作为链表的第 1 个元素
*/
Status HeadInsert(ElemType e, LinkList list)
{
	if (!list) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	// 创建新结点 
	LinkList newLNode = MakeNewLNode(e);
	if (!newLNode) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	// 插入新元素 
	newLNode->next = list->next;
	list->next = newLNode;

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在
	操作结果:在 list 的尾部插入新的数据元素 e, 作为链表的最后一个元素
*/
Status EndInsert(ElemType e, LinkList list)
{
	if (!list) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	// list 指向线性表的最后一个位置 
	while (list->next) {
		list = list->next;
	}

	LinkList newLNode = MakeNewLNode(e);
	if (!newLNode) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	list->next = newLNode;

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在,且有不少于 1 个元素
	操作结果:删除 list 的第 1 个数据元素,并由 *e 返回其值
*/
Status DeleteFirst(LinkList list, ElemType *e)
{
	if (!list || !e) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, e = %p", list, e);
		return ERR_NULL_PTR;
	}

	if (!(list->next)) {
		ERR_RECORD(ERR_NOT_EXIST);
		return ERR_NOT_EXIST;
	}

	// 删除第 1 个元素 
	*e = list->next->data;
	LinkList p = list->next;
	list->next = p->next;
	free(p);

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在,且有不少于 1 个元素
	操作结果:删除 list 的最后一个数据元素,并用 *e 返回其值
*/
Status DeleteTail(LinkList list, ElemType *e)
{
	if (!list || !e) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, e = %p", list, e);
		return ERR_NULL_PTR;
	}

	if (!(list->next)) {
		ERR_RECORD(ERR_NOT_EXIST);
		return ERR_NOT_EXIST;
	}

	// 找到最后一个元素,且 p 指向最后一个元素,q 指向 p 的前一个元素 
	LinkList p = list, q = NULL;
	while (p->next) {
		q = p;
		p = p->next;
	}

	// 删除最后一个元素 
	q->next = NULL;
	*e = p->data;
	free(p);

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在
	操作结果:删除表中值为 e 的元素
*/
Status DeleteElem(ElemType e, Boolean(*compare)(ElemType, ElemType),
	LinkList list)
{
	if (!list) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	LinkList p = list, q = NULL;

	// 遍历找到值为 e 的元素,且只删除一次 
	while (p) {
		q = p->next;
		if ((q) && compare(q->data, e)) {
			p->next = q->next;
			free(q);

			// 如果要删除线性表中所有值为 e 的元素,则添加语句 continue; (已经过测试验证)
			// 并去掉 return RET_OK; 并加上其他修改 
			return RET_OK;
		}

		p = q;
	}

	ERR_RECORD(ERR_NOT_EXIST);

	return ERR_NOT_EXIST;
}

/*
	前置条件:线性表 list 已存在
	操作结果:用 e 取代表 list 中第 i 个元素的值
*/
Status RePlaceElem(int i, ElemType e, LinkList list)
{
	if (!list) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	// 使 list 指向第 i 个元素 
	int j = 0;
	while ((list->next) && (j < i)) {
		++j;
		list = list->next;
	}

	if (j != i) {
		ERR_RECORD(ERR_NOT_EXIST, "j = %d, i = %d", j, i);
		return ERR_NOT_EXIST;
	}

	list->data = e;

	return RET_OK;
}

/*
	前置条件:线性表 list 已存在
	操作结果:返回表头元素的值
*/
Status GetFirstElem(LinkList list, ElemType *e)
{
	if (!list || !e) {
		ERR_RECORD(ERR_NULL_PTR, "list = %p, e = %p", list, e);
		return ERR_NULL_PTR;
	}

	if (!(list->next)) {
		ERR_RECORD(ERR_NOT_EXIST);
		return ERR_NOT_EXIST;
	}

	*e = list->next->data;

	return RET_OK;
}

4) algorithm.h

// 算法定义头文件

#ifndef ALGORITHM_H
#define ALGORITHM_H

#include "singleLinkList.h"

Status CreateListHead(int n, LinkList *list);

Status CreateListTail(int n, LinkList *list);

Status MergeList(LinkList listA, int(*compare)(ElemType, ElemType),
	LinkList *listB, LinkList *listC);

Status Union(LinkList listB, LinkList listA);

Status MergeList2(LinkList listA, LinkList listB, int(*compare)(ElemType, ElemType),
	LinkList *listC);

#endif // !ALGORITHM_H

5) algorithm.c

// 算法实现源文件

#include "algorithm.h"
#include "auxiliary.h"
#include <stdlib.h>
#include <stdio.h>

/*
	前置条件:list 非空
	操作结果:创建具有 n 个节点的线性表
*/
static Status CreateList(int n, Status(*Insert)(ElemType, LinkList), LinkList *list)
{
	Status ret = InitList(list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	printf("Please input %d integers: ", n);
	ElemType e;
	for (int i = 0; i < n; ++i) {
		scanf_s("%d", &e);
		ret = Insert(e, *list);
		if (ret != RET_OK) {
			ERR_RECORD(ret);
			return ret;
		}
	}

	return RET_OK;
}

/*
	算法 2.11
	前置条件:list 非空
	操作结果:逆位序(插在表头)输入 n 个元素的值,建立带表头结构的单链线性表 *list
*/
Status CreateListHead(int n, LinkList *list)
{
	if (!list) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	if (n < 1) {
		ERR_RECORD(ERR_PARA_ILLEGAL, "n = %d", n);
		return ERR_PARA_ILLEGAL;
	}

	Status ret = CreateList(n, HeadInsert, list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
	}

	return ret;;
}

/*
	前置条件:list 非空
	操作结果:正位序(插在表尾)输入 n 个元素的值,建立带表头结构的单链线性表 *list
*/
Status CreateListTail(int n, LinkList *list)
{
	if (!list) {
		ERR_RECORD(ERR_NULL_PTR);
		return ERR_NULL_PTR;
	}

	if (n < 1) {
		ERR_RECORD(ERR_PARA_ILLEGAL, "n = %d", n);
		return ERR_PARA_ILLEGAL;
	}

	Status ret = CreateList(n, EndInsert, list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
	}

	return ret;
}

/*
	算法 2.12
	前置条件:已知单链线性表 listA 和 *listB 的元素按值非递减排列
	操作结果:归并 listA 和 *listB 得到新的单链线性表 *listC,*listC 的元素也按值非递减排列,
			  此处需要将 *listB 头节点指针置空故需要传入 listB 指针变量
*/
Status MergeList(LinkList listA, int(*compare)(ElemType, ElemType),
	LinkList *listB, LinkList *listC)
{
	if (!listA || !compare || !listB || !listC) {
		ERR_RECORD(ERR_NULL_PTR, "listA = %p, compare = %p, listB = %p, listC = %p",
			listA, compare, listB, listC);
		return ERR_NULL_PTR;
	}

	LinkList pa = listA->next, pb = (*listB)->next, pc = NULL;
	*listC = pc = listA;
	while (pa && pb) {
		if (compare(pa->data, pb->data) <= 0) {
			pc->next = pa;
			pc = pa;
			pa = pa->next;
			continue;
		}

		pc->next = pb;
		pc = pb;
		pb = pb->next;
	}

	/* pa 不为空,则赋值 pa, 否则赋值 pb */
	pc->next = pa ? pa : pb;
	free(*listB);
	*listB = NULL;

	return RET_OK;
}

/*
	算法 2.1
	前置条件:已知单链线性表 listA 和 *listB 的元素按值非递减排列
	操作结果:单链表实现,将所有在线性表 listB 中但不在 listA 中的数据元素插入到 listA 中
*/
Status Union(LinkList listB, LinkList listA)
{
	if (!listB || !listA) {
		ERR_RECORD(ERR_NULL_PTR, "listB = %p, listA = %p", listB, listA);
		return ERR_NULL_PTR;
	}

	int listALength, listBLength;
	ListLength(listA, &listALength);
	ListLength(listB, &listBLength);

	ElemType e;
	int pos;
	Status ret;

	for (int i = 1; i <= listBLength; ++i) {
		ret = GetElem(listB, i, &e);
		if (ret != RET_OK) {
			ERR_RECORD(ret, "i = %d", i);
			return ret;
		}

		ret = LocateElem(listA, e, Equal, &pos);
		if (ret == RET_OK) {
			continue;
		}

		ret = ListInsert(++listALength, e, listA);
		if (ret != RET_OK) {
			ERR_RECORD(ret, "listALength = %d", listALength);
			return ret;
		}
	}

	return RET_OK;
}

/*
	算法 2.2
	前置条件:单链表实现,已知线性表 listA 和listB 中的数据元素按值非递减排列
	操作结果:归并 listA 和listB 得到新的线性表 listC, listC 的数据元素也按值非递减排列
*/
Status MergeList2(LinkList listA, LinkList listB, int(*compare)(ElemType, ElemType),
	LinkList *listC)
{
	if (!listA || !listB || !compare || !listC) {
		ERR_RECORD(ERR_NULL_PTR, "listA = %p, listB = %p, compare = %p, listC = %p",
			listA, listB, compare, listC);
		return ERR_NULL_PTR;
	}

	Status ret = InitList(listC);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	int listALength, listBLength;
	ListLength(listA, &listALength);
	ListLength(listB, &listBLength);

	int i = 1, j = 1, k = 0;
	ElemType ai, bj;
	while ((i <= listALength) && (j <= listBLength)) {
		ret = GetElem(listA, i, &ai);
		ret |= GetElem(listB, j, &bj);
		if (ret != RET_OK) {
			ERR_RECORD(ret, "i = %d, j = %d", i, j);
			return ret;
		}

		if (compare(ai, bj) <= 0) {
			ret = ListInsert(++k, ai, *listC);
			if (ret != RET_OK) {
				ERR_RECORD(ret, "k = %d, ai = %d", k, ai);
				return ret;
			}

			++i;
			continue;
		}

		ret = ListInsert(++k, bj, *listC);
		if (ret != RET_OK) {
			ERR_RECORD(ret, "k = %d, bj = %d", k, bj);
			return ret;
		}

		++j;
	}

	while (i <= listALength) {
		ret = GetElem(listA, i++, &ai);
		ret |= ListInsert(++k, ai, *listC);
		if (ret != RET_OK) {
			ERR_RECORD(ret, "k = %d, ai = %d", k, ai);
			return ret;
		}
	}

	while (j <= listBLength) {
		ret = GetElem(listB, j++, &bj);
		ret |= ListInsert(++k, bj, *listC);
		if (ret != RET_OK) {
			ERR_RECORD(ret, "k = %d, bj = %d", k, bj);
			return ret;
		}
	}

	return RET_OK;
}

6) auxiliary.h

// 辅助函数头文件

#ifndef AUXILIARY_H
#define AUXILIARY_H

#include "singleLinkList.h"

void Visit(ElemType e);

Boolean Equal(ElemType e1, ElemType e2);

int Compare(ElemType e1, ElemType e2);

Status CreateSingleLinkList(int n, int(*compare)(ElemType, ElemType),
	Boolean isAscend, LinkList *list);

Status ShowList(char str[], LinkList L);

#endif // !AUXILIARY_H

7) auxiliary.c

// 辅助函数实现源文件

#include "auxiliary.h"

/*
	前置条件:无
	操作结果:辅助函数,打印整形元素值 e
*/
void Visit(ElemType e)
{
	printf("%d ", e);
}

/*
	前置条件:无
	操作结果:辅助函数,判断元素 e1 和 e2 是否相等
*/
Boolean Equal(ElemType e1, ElemType e2)
{
	return (e1 == e2) ? TRUE : FALSE;
}

/*
	前置条件:无
	操作结果:辅助函数,判断元素 e1 和 e2 大小
*/
int Compare(ElemType e1, ElemType e2)
{
	return e1 - e2;
}

/*
	前置条件:list 非空
	操作结果:根据 isAscend 是否为 TRUE 建立 n 个元素的非降序(非升序)线性表
*/
Status CreateSingleLinkList(int n, int(*compare)(ElemType, ElemType),
	Boolean isAscend, LinkList *list)
{
	if (!compare || !list) {
		ERR_RECORD(ERR_NULL_PTR, "compare = %p, list = %p", compare, list);
		return ERR_NULL_PTR;
	}

	if (n < 1) {
		ERR_RECORD(ERR_PARA_ILLEGAL, "n = %d", n);
		return ERR_PARA_ILLEGAL;
	}

	/* 初始化线性表 */
	Status ret = InitList(list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	printf("Please input %d elements: ", n);

	/* 先将第 1 个元素插入线性表中 */
	ElemType e;
	scanf_s("%d", &e);
	LinkList newLNode = MakeNewLNode(e);
	if (!newLNode) {
		ERR_RECORD(ERR_MEMORY_ALLOCATE);
		return ERR_MEMORY_ALLOCATE;
	}

	(*list)->next = newLNode;

	/* 后续按照要求插入其余 n - 1 个元素 */
	if (isAscend) {
		for (int i = 0; i < n - 1; ++i) {
			scanf_s("%d", &e);
			ret = InsertAscend(e, compare, *list);
			if (ret != RET_OK) {
				ERR_RECORD(ret);
				return ret;
			}

		}

		return RET_OK;
	}

	for (int i = 0; i < n - 1; ++i) {
		scanf_s("%d", &e);
		ret = InsertDescend(e, compare, *list);
		if (ret != RET_OK) {
			ERR_RECORD(ret);
			return ret;
		}
	}

	return RET_OK;
}

/*
	前置条件:无
	操作结果:辅助函数,格式化打印 list 中的元素
*/
Status ShowList(char str[], LinkList list)
{
	printf("%s", str);
	Status ret = ListTraverse(list, Visit);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	putchar('\n');

	return RET_OK;
}

8) main.c

// 主函数入口源文件

#include "singleLinkList.h"
#include "algorithm.h"
#include "auxiliary.h"
#include <stdio.h>

int main(void)
{
	int n = 5;
	LinkList listA, listB, listC;
	Status ret = CreateListHead(n, &listA);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("listA is: ", listA);

	ret = CreateListTail(n, &listB);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("listB is: ", listB);

	ret = MergeList(listA, Compare, &listB, &listC);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("listC is: ", listC);

	DestroyList(&listC);

	// free() 的作用:仅仅是释放堆内存,不将指针置空
	printf("After Destroy list listC, listC is %p\n", listC);

	// 算法 2.1 单链表实现测试
	ret = CreateListTail(n, &listA);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("listA is: ", listA);

	ret = CreateListTail(n, &listB);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("listB is: ", listB);

	ret = Union(listB, listA);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("listA is: ", listA);
	ShowList("listB is: ", listB);
	DestroyList(&listA);
	DestroyList(&listB);

	// 算法 2.2 单链表实现测试
	ret = CreateListTail(n, &listA);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("listA is: ", listA);

	ret = CreateListTail(n, &listB);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("listB is: ", listB);

	ret = MergeList2(listA, listB, Compare, &listC);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("listC is: ", listC);

	DestroyList(&listA);
	DestroyList(&listB);
	DestroyList(&listC);

	// 测试其他
	LinkList list;
	printf("Please input the element num of list for create ascend: ");
	int num;
	scanf_s("%d", &num);

	ret = CreateSingleLinkList(num, Compare, TRUE, &list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("list is: ", list);

	ret = InsertAscend(10, Compare, list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	printf("After insert 10 for ascend, ");
	ShowList("list is: ", list);

	ret = HeadInsert(12, list);
	ret |= EndInsert(9, list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	printf("After insert 12 in the head of list, insert 9 in the tail of list, ");
	ShowList("list is: ", list);

	ElemType e;
	printf("Please input the element to be delete: ");
	scanf_s("%d", &e);
	ret = DeleteElem(e, Equal, list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	printf("delete %d %s\n", e, "success");

	ShowList("list is: ", list);

	printf("Please input the order of the element to be replace and the new value: ");
	scanf_s("%d%d", &num, &e);

	ret = RePlaceElem(num, e, list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("list is: ", list);
	DestroyList(&list);

	printf("Create list for descend, please input the num of list: ");
	scanf_s("%d", &num);

	ret = CreateSingleLinkList(num, Compare, FALSE, &list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	ShowList("list is: ", list);

	ret = InsertDescend(10, Compare, list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	printf("After insert 10 in list for descend, ");
	ShowList("list is: ", list);

	printf("Please input the element to be delete: ");
	scanf_s("%d", &e);
	ret = DeleteElem(e, Equal, list);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	printf("delete %d %s\n", e, "success");
	ShowList("list is: ", list);

	ElemType e2;
	ret = DeleteFirst(list, &e);
	ret |= DeleteTail(list, &e2);
	if (ret != RET_OK) {
		ERR_RECORD(ret);
		return ret;
	}

	printf("After delete head element %d and tail element %d, ", e, e2);
	ShowList("list is: ", list);
	DestroyList(&list);

	return 0;
}

3. 运行示例(DEBUG OFF)

1)测试输入

5 4 3 2 1
2 4 6 8 10
1 2 3 4 5
2 4 6 8 10
1 2 3 4 5
2 4 6 8 10
5
1 3 2 5 8
12
7 11
5
1 3 2 5 8
8

2)测试输出 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值