链表是一种动态结构,创建链表时,无须知道链表长度,插入一个节点时,只需为新节点分配内存,然后调整指针。
1.单向链表定义
struct ListNode
{
int data;
ListNode *pNext;
};
2.链表插入节点
void InsertNode(ListNode** pHead,int data)//pHead头指针
{
ListNode* pNew = new ListNode();
pNew->data = data;
pNew->pNext = NULL;
if(*pHead == NULL)
{
*pHead = pNew;//链表为空时新插入一个节点后,节点就是链表的头指针
}
else
{
ListNode *pNode = *pHead;//遍历指针
while(pNode->pNext != NULL)
pNode = pNode->pNext;//不断遍历直到最后一个,然后插入
pNode->pNext = pNew;
}
}
3.链表删除节点
链表内存不是连续的,所以找第i个节点时,需要从开头遍历。效率为O(n).以下为删除链表中含有某值的节点
void DeleteNode(ListNode** pHead,int data)
{
if(pHead == NULL || *pHead == NULL)
return;
ListNode* pToBeDelete = NULL;//初始化要删除的节点
if((*pHead)->data == data)//头指针就是要删除的节点
{
pToBeDelete = *pHead;
*pHead = (*pHead)->pNext;
}
else
{
//如果节点不是尾节点,且节点的下个节点不是要删除的节点,则往下遍历
ListNode* pNode = *pHead;
while(pNode->pNext != NULL && pNode->pNext->data != data)
pNode = pNode->pNext;
//如果下个节点是要删除的,则pNode指向下下个节点
if(pNode->pNext != NULL && pNode->pNext->data == data)
{
pToBeDelete = pNode->pNext;
pNode->pNext = pNode->pNext->pNext;
}
//删节点释放内存
if(pToBeDelete != NULL)
{
delete pToBeDelete;
pToBeDelete = NULL;
}
}
}
剑指offer
1.面试题5——从尾到头打印链表
2.面试题13——在O(1)时间删除链表节点
3.面试题15——链表倒数第k个节点
4.面试题16——反转链表
5.面试题17——合并两个排序的链表
6.面试题26——复杂链表的复制
7.面试题37——两个链表的第一个公共节点
编程之美
8.3.4——从无头单链表中删除节点
july
9.79——链表排序的算法
10.给单链表建环
11检测单链表是否有环
12.约瑟夫环
13.双向链表与二叉树