链表
链表是一种动态的数据结构,在创建链表时,无需知道链表的长度。内存分配是链表在添加结点是才分配的。
单链表的结点定义:
struct ListNode{
int m_nvalue; //数据域
ListNode * m_pNext; //指针域
};
链表的操作:
向链表的末尾添加结点
void AddToTail(ListNode** pHead, 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;
}
}
在链表中找到第一个含有某值的结点并删除该结点的代码
void RemoveNode(ListNode** pHead, int value){
if(pHead == NULL || *pHead == NULL)
return ;
ListNode* pToBeDeleted = NULL;
if((*pHead)->m_nValue == value){
pToBeDeleted = *pHead;
*pHead = (*pHead)->m_pNext;
}else{
ListNode* pNode = *pHead;
while(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue != value)
pNode = pNode->m_pNext;
if(pNode->m_pNext != NULL && pNode->m_pNext->m_nValue == value){
pToBeDeleted = pNode->m_pNext;
pNode->m_pNext = pNode->m_pNext->m_pNext;
}
}
if(pToBeDeleted != NULL){
delete pToBeDeleted ;
pToBeDeleted = NULL;
}
}
5.输入一个链表的头结点,从尾到头反过来打印出每个结点的值。(循环、递归、栈)
链表的结点定义:
struct ListNode{
int m_nKey;
ListNode* m_pNext;
};
解法1:
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();
}
}
利用栈实现逆序输出。每经过一个结点时,把该结点放入到一个栈中。当遍历完整个链表后,再从栈顶开始逐个输出结点的值。
解法2:
void PrintListReversingly_Recursively(ListNode* pHead){
if(Head != NULL){
if(pHead->m_pNext != NULL){
PrintListReversingly_Recursively(pHead->m_pNext);
}
printf("%d\t", pHead->m_nValue);
}
}
每次访问一个结点时,先递归输出它后面的结点,再输出该结点自身。
测试用例:
(1)功能测试(输入的链表有多个结点,输入的链表只有一个结点)。
(2)特殊输入测试(输入的链表头结点指针为NULL)