今天重新看了一遍以前自己写的博客文章,考虑到从自学开始以来至今,代码优化迭代已经多次,所以重新整理,将代码分享出来。
非循环单向动态链表是一个十分基础但很重要的数据结构,对于理解指针的概念百利而无一害,同时也几乎是各个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);
我希望它有以下功能:
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);