数据结构之链表
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构之链表相关的知识,希望对你有一定的参考价值。
(本文参考《剑指offer》总结笔记,供学习使用)
链表是一种动态数据结构,是因为在创建链表的时候,无须知道链表的长度。当插入一个结点时,我们只需要为新结点分配内存,然后调整指针的指向来确保新节点被链接到链表当中。由于没有闲置的内存,链表的空间效率比数组高。
单向链表的结点定义为:
struct ListNode { int m_nValue; ListNode* m_pNext; };
例:往链表的结尾添加一个结点:
void AddToTail(ListNode** pHead, int value) { //pHead是一个指向指针的指针。因为当我们往一个空链表中插入一个结点时,新插入的结点是链表 //的头指针。由于此时会改动头指针,因此必须把pHead参数设为指向指针的指针,否则出了这个函数 //pHead仍然是一个空指针。 ListNode* pNew=new ListNode(); pNew->m_nValue=value; pNew->m_pNext=NULL; if(*pHead==NULL) *pHead=pNew; else { ListNode* pNode=*pHead; while(pNode->m_pNext!=NULL) pNode=pNode->m_pNext; pNode->m_pNext=pNew; } }
注:由于链表中的内存不是一次性分配的,因此我们无法保证链表和数组一样是连续的。
例:从尾到头打印链表
//使用栈结构打印链表 void PrintListReversingly_Iteratively(ListNode* pHead) { std::stack<ListNode*> nodes; ListNode* pNode = pHead; while(pNode != NULL) { nodes.push(pNode); pNode = pNode->m_pNext; } while(!nodes.empty()) { pNode = nodes.top(); printf("%d\t", pNode->m_nValue); nodes.pop(); } } //使用递归打印链表 void PrintListReversingly_Recursively(ListNode* pHead) { if(pHead != NULL) { if (pHead->m_pNext != NULL) { PrintListReversingly_Recursively(pHead->m_pNext); } printf("%d\t", pHead->m_nValue); } }
注:基于递归代码简洁,但是当链表非常长的时候,就会导致函数调用层级很深,从而有可能导致函数调用栈溢出。显示用栈基于循环实现的代码鲁棒性更好。
本文出自 “11773640” 博客,谢绝转载!
以上是关于数据结构之链表的主要内容,如果未能解决你的问题,请参考以下文章