数据结构学习之链表(单向、单循环以及双向)(递归实现)

1、链表优点

相比较普通的线性结构,链表结构的优势是什么呢?我们可以总结一下: (1)单个节点创建非常方便,普通的线性内存通常在创建的时候就需要设定数据的大小 (2)节点的删除非常方便,不需要像线性结构那样移动剩下的数据 (3)节点的访问方便,可以通过循环或者递归的方法访问到任意数据,但是平均的访问效率低于线性表 那么在实际应用中,链表是怎么设计的呢?我们可以以int数据类型作为基础,设计一个简单的int链表:

2、单向链表

(1)设计链表的数据结构

typedef struct _LINK_NODE{int data;//数据域struct _LINK_NODE* next;//指针域}LINK_NODE;

(2)创建链表

LINK_NODE* alloca_node(int value)//创建链表,分配大小,并赋值{LINK_NODE* pLinkNode = NULL;pLinkNode = (LINK_NODE*)malloc(sizeof(LINK_NODE));pLinkNodevalue;pLinkNode->next = NULL;return pLinkNode;}

(3)删除链表

void delete_node(LINK_NODE** pNode){LINK_NODE** pNext;pNode)return ;pNext = &(*pNode)->next;//链表下一个结点保存下来free(; //释放后,加NULLdelete_node(pNext); //遍历下一个结点,不断迭代}

(4)链表插入数据

STATUS _add_data(LINK_NODE** pNode, LINK_NODE* pDataNode){if(NULL == *pNode){ //尾结点*pNode = pDataNode;return TRUE;}return _add_data(&(*pNode)->next, pDataNode);}LINK_NODE** pNode, int value){LINK_NODE* pDataNode;;pDataNode = alloca_node(value);//分配大小assert(NULL != pDataNode);;}

(5)链表删除数据

STATUS _delete_data(LINK_NODE** pNode, int value){LINK_NODE* pLinkNode;if(NULL == (*pNode)->next)return FALSE;pLinkNode = &(*pNode)->next;if(value == pLinkNode->data){(*pNode)->next = pLinkNode->next;//保存下来free(pLinkNode);pLinkNode = NULL;return TRUE;}else{return _delete_data(&(*pNode)->next, value);//继续遍历}}STATUS delete_data(LINK_NODE** pNode, int value){LINK_NODE* pLinkNode;pNode)return FALSE;if(value == (*pNode)->data){ //pLinkNode = *pNode;*pNode = pLinkNode->next;//保存下来free(pLinkNode);pLinkNode = NULL;return TRUE;}return _delete_data(pNode, value);}

(6)链表查找数据

LINK_NODE* find_data(const LINK_NODE* pLinkNode, int value){if(NULL == pLinkNode)return NULL;if(value == pLinkNode->data)return (LINK_NODE*)pLinkNode;return find_data(pLinkNode->next, value);}

(7)打印链表数据

void print_node(const LINK_NODE* pLinkNode){if(pLinkNode){printf(“%d\n”, pLinkNode->data);print_node(pLinkNode->next);}}

(8)统计数据

int count_node(const LINK_NODE* pLinkNode){if(NULL == pLinkNode)return 0;return 1 + count_node(pLinkNode->next);}3、单循环链表

单链表是指最后一个节点的指针是空指针,我们将终端结点指针端由空指针指向头结点,就使整个链表形成一个环,这种头尾相接的单链表就成为单循环链表。

(1)打印链表数据

void print_data(const LINK_NODE* pLinkNode){LINK_NODE* pIndex = NULL;;printf(“%d\n”, pLinkNode->data);pIndex = pLinkNode->next;while(pLinkNode != pIndex){ //尾结点后面一个结点是不是头结点printf(“%d\n”, pIndex->data);pIndex = pIndex ->next;}}

以往,我们发现打印数据的结束都是判断指针是否为NULL,这里因为是循环链表所以发生了变化。原来的条件(NULL != pLinkNode)也修改成了这里的(pLinkNode != pIndex)。同样需要修改的函数还有find函数、count统计函数。

(2)链表插入数据

STATUS insert_data(LINK_NODE** ppLinkNode, int data){LINK_NODE* pNode;if(NULL == ppLinkNode)return FALSE;ppLinkNode){pNode = create_link_node(data);assert(NULL != pNode);pNode->next = pNode;*ppLinkNode = pNode;return TRUE;}if(NULL != find_data(*ppLinkNode, data))return FALSE;pNode = create_link_node(data);assert(NULL != pNode);pNode->next = (*ppLinkNode)->next;(*ppLinkNode)->next = pNode;return TRUE;}流过泪的眼睛更明亮,滴过血的心灵更坚强!

数据结构学习之链表(单向、单循环以及双向)(递归实现)

相关文章:

你感兴趣的文章:

标签云: