链表:
struct ListNode{
int value;
ListNode * next;
}
一般链表要注意的特殊输入是链表为空,链表只有一个结点等。
一、在链表末尾添加一个节点
void addToTail(ListNode ** pHead,int value){
ListNode newListNode = new ListNode();
newListNode -> value = value;
newListNode -> next = null;
if(pHead == null || *pHead == null)
*pHead = newListNode;
else{
ListNode *pNode = *pHead;
while(pNode -> next != null){
pNode = pNode ->next;
}
pNode ->next = newListNode;
}
}
为什么这里的参数是指向指针的指针?因为如果参数只是一个指针,而它指向的是null,那么如果在函数中将pHead=newListNode,那么出了这个函数pHead仍旧为null。
例如:如果函数为void addToTail(ListNode * pHead,int value); 传递来的参数为(pRoot,value); 那么实际上我们传进来的实际上是pRoot的一个副本,这个副本等于newListNode,而pRoot实际上指向的还是null。所以,如果一个函数涉及到头指针的变动就要以头指针的指针作为函数参数。
二、从尾到头打印链表
方法一、利用递归的方法实现,缺点:当链表很长时,会导致函数调用的层级很深,从而有可能导致函数调用栈溢出。
void printReverseList(ListNode * pHead){
if(pHead != null){
ListNode * pNode = pHead;
if(pHead -> next == null)
printf("%d\t",pNode -> value);
printReverseList(pHead -> next);
}
}
方法二、利用栈实现
void printReverseList(ListNode * pHead){
std::stack<ListNode*> nodes;
ListNode * pNode = pHead;
while(pNode != null){
nodes.push(pNode);
pNode = pNode -> next;
}
while(!nodes.empty()){
pNode = nodes.top();
printf("%d\t",pNode -> value);
nodes.pop();
}
}
三、打印倒数第k个节点
方法一:如果链表共有n个节点,倒数第1