链表
链表的创建、插入节点、删除节点等操作比较简单,其代码量适合笔试和面试。
链表是有种动态数据结构,创建链表时,无须知道链表的长度。当插入一个节点时,只需为新节点分配内存,然后调整指针的指向来确保新节点被链接到链表中。内存分配不是在创建链表时一次性完成的,而是每添加一个节点分配一次内存。
单向链表的节点定义如下:
struct ListNode
{
int m_nValue;
ListNode* m_pNext;
};
往链表末尾中添加一个节点的代码如下:
void AddToTail(ListNode ** pHead</span>,int value)
{
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;
}
}
上面的代码中,函数的第一个参数pHead是一个指向指针的指针。当向一个空链表中插入一个节点时,新插入的节点就是链表的头指针。由于此时会改动头指针,因此必须把pHead参数设为指向指针的指针,否则出了这个函数pHead任然是一个空指针。
由于链表中的内存不是一次性分配的,因而无法保证链表的内存和数组一样是连续的。若想再链表中找到它的第i个节点,只能从头结点开始,沿着指向下一个节点的指针遍历链表,它的时间效率为O(n)。而在数组中,可根据下表在O(1)时间内找到第i个元素。
下面是在链表中找到一个含有某值的节点并删除该节点的代码:
void RemoveNode(ListNode** pHead,int value)
{
if(pHead == NULL || *pHead == NULL)
return;
ListNode* pToBeDeleted = NULL;
if((*pHead)->n_mValue == value)
{
pToBeDeleted = *pHead;
*pHead = (*pHead)->n_pNext;
}
else
{
ListNode* pNode = *pHead;
while(pNode->m_pNext != NULL && pNode->m_pNext->n_mValue != value)
pNode = pNode->n_pNext;
if(pNode->m_pNext !=NULL && pNode->n_pNext->n_mValue ==value)
{
pToBeDeleted = pNode->n_pNext;
pNode->m_pNext = pNode->n_pNext->n_pNext;
}
}
if(pToBeDeleted !=NULL)
{
delete pToBeDeleted;
pToBeDeleted =NULL;
}
}