创建非循环单向动态链表

今天重新看了一遍以前自己写的博客文章,考虑到从自学开始以来至今,代码优化迭代已经多次,所以重新整理,将代码分享出来。

 非循环单向动态链表是一个十分基础但很重要的数据结构,对于理解指针的概念百利而无一害,同时也几乎是各个IT公司面试都会问到的相关问题,本文介绍链表中的单向动态链表;

需求列表

对该非循环单向动态链表,我希望它能提供以下功能的API接口:

  • 创建链表
  • 插入节点
  • 删除节点
  • 打印整个链表
  • 销毁整个链表

因此,有以下API需要声明:

int create_single_ll(pstEntry_single_ll *pL, int volume);
#define LIST_EMPTY_LL(L) (!(L)->head ? TRUE : FALSE)
#define LIST_FULL_LL(L) ((L)->size + 1 > (L)->volume ? TRUE : FALSE)
int insert_single_ll(const pstEntry_single_ll L, pstNode elm, int k);
int delete_single_ll(const pstEntry_single_ll L, pstNode *pelm, int k);
void print_single_ll(const pstEntry_single_ll L);
int destroy_single_ll(pstEntry_single_ll *pL);

创建单向动态链表

我希望它有以下功能:

  1. 可对链表节点计数;
  2. 提供最大链表节点限制;
  3. 运行时创建节点;
  4. 每个链表拥有自己的名字;
typedef struct stElemtype_singleLL{
	int scores;
}stElemtype_singleLL,*pstElemType_singleLL;
typedef struct node{
	stElemtype_singleLL data;
	struct node * next;
}stNode,*pstNode, **ppstNode;
typedef struct entry_single_ll {
	pstNode head;
	int size;
	int volume;
	stString name;
}stEntry_single_ll, *pstEntry_single_ll;
int create_single_ll(pstEntry_single_ll *pL, int volume) {
	REG_FUNC_NAME("create_single_ll");
	enErr_val enRetVal = ERR_SUCCESS;
	if (*pL)	*pL = NULL;
	if (volume < 0)	RET_LOCAL(enRetVal = ERR_INVALID_PARAMETER);
	*pL = (pstEntry_single_ll)malloc(sizeof(stEntry_single_ll));
	(*pL)->head = NULL;
	(*pL)->size = 0;
	(*pL)->volume = volume;
	(*pL)->name.iLen = 0;
	(*pL)->name.pStr = NULL;
	RET_LOCAL(enRetVal)
}

插入节点

需求:在第k个节点之前插入一个节点

int insert_single_ll(const pstEntry_single_ll L, pstNode elm, int k) {
	REG_FUNC_NAME("insert_single_ll");
	enErr_val enRetVal = ERR_SUCCESS;
	if (!L || !elm || k < 1)	RET_LOCAL(enRetVal = ERR_INVALID_PARAMETER);
	if (LIST_FULL_LL(L)) RET_LOCAL(enRetVal = ERR_ARRIVE_TAIL);
	if (LIST_EMPTY_LL(L) || k == 1) {
		if (k > 1) RET_LOCAL(enRetVal = ERR_NOT_ENOUGH_ELEMENT);
		elm->next = L->head;
		L->head = elm;
	}
	else {
		pstNode pCur = L->head;
		while (k > 2 && pCur->next) {
			--k;
			pCur = pCur->next;
		}
		if (k > 2) RET_LOCAL(enRetVal = ERR_ARRIVE_TAIL);
		elm->next = pCur->next;
		pCur->next = elm;
	}
	++L->size;
	RET_LOCAL(enRetVal)
}

删除节点

需求:删除第k个节点

int delete_single_ll(const pstEntry_single_ll L, pstNode *pelm, int k) {
	REG_FUNC_NAME("delete_single_ll");
	enErr_val enRetVal = ERR_SUCCESS;
	if (!L || k < 1)	RET_LOCAL(enRetVal = ERR_INVALID_PARAMETER)
	if (LIST_EMPTY_LL(L))	RET_LOCAL(enRetVal = ERR_LIST_EMPTY)
	if (!L->head->next || k == 1) {
		if (k > 1)	RET_LOCAL(enRetVal = ERR_NOT_ENOUGH_ELEMENT)
			*pelm = L->head;
		L->head = (*pelm)->next;
	}
	else {
		pstNode pCur = L->head;
		while (k > 2 && pCur->next) {
			--k;
			pCur = pCur->next;
		}
		if (k > 2 || !pCur->next)	RET_LOCAL(enRetVal = ERR_ARRIVE_TAIL)
			(*pelm) = pCur->next;
		pCur->next = (*pelm)->next;
	}
	--L->size;
	RET_LOCAL(enRetVal)
}

销毁链表

需求:必须彻底删除并释放与这个链表有关的内存

int destroy_single_ll(pstEntry_single_ll *pL) {
	REG_FUNC_NAME("destroy_single_ll");
	enErr_val enRetVal = ERR_SUCCESS;
	if (!(*pL))	RET_LOCAL(enRetVal = ERR_INVALID_PARAMETER);
	pstNode pCur = NULL;
	while (!LIST_EMPTY_LL(*pL)) {
		delete_single_ll(*pL, &pCur, 1);
		free(pCur);
	}
	free(*pL);
	printf("the single linked list is destroyed!\n");
	RET_LOCAL(enRetVal)
}

打印输出链表

void print_single_ll(const pstEntry_single_ll L) {
	REG_FUNC_NAME("print_single_ll");
	if (!L)	return;
	pstNode pCur = L->head;
	int i = 0;
	while (pCur) {
		printf("%d-th:%d, addr:%x, next addr:%x\n",
			++i, pCur->data, pCur, pCur->next);
		pCur = pCur->next;
	}
}

测试用例与结果

        pstEntry_single_ll L;
	pstNode pelm = NULL;
	create_single_ll(&L, 5);
	for (int i = 0; i < 3; ++i) {
		pelm = (pstNode)malloc(sizeof(stNode));
		if (!pelm)	RET_LOCAL(enRetVal = ERR_MEMORY_ALLOC);
		pelm->data.scores = i;
		pelm->next = NULL;
		insert_single_ll(L, pelm, i);
	}
	print_single_ll(L);
	pelm = (pstNode)malloc(sizeof(stNode));
	if (!pelm)	RET_LOCAL(enRetVal = ERR_MEMORY_ALLOC);
	pelm->data.scores = 50;
	pelm->next = NULL;
	insert_single_ll(L, pelm, 2);
	putchar('\n');
	delete_single_ll(L, &pelm, 1);
	print_single_ll(L);
	destroy_single_ll(&L);

创建非循环单向动态链表_第1张图片

你可能感兴趣的:(C,数据结构,self,education)