****单链表操作之删除倒数第k个结点****
//函数功能:删除链表的倒数第k个结点;1<k<链表总长度
//自定义的结点结构体和头指针结构体:
typedef int DataType;
typedef struct LinkNode
{
DataType data;
struct LinkNode* next;
}LinkNode,*pLinkNode;//结点结构体
typedef struct LinkList
{
LinkNode* pHead;//头结点指针
}LinkList ,*pLinkList;//链表
//函数原型:void DelKNode(pLinList pList, int k);
ps:我在博客中每次的思路分析,只是将我的对每道题的理解和思考列出来,里面会有我做题时思考的经过,各种失败的尝试等等,希望我的分析思路可以帮助到大家,但是并不是每个人的思考方法都是一样的,所以思路分析只是帮助理解!
//思路分析: 删除链表的倒数第k个结点,首先反映到大脑的方法就是找出链表一共有多少个元素,然后在通过遍历链表找到倒数第K个结点; 不可否认的是这种方法是可以做到的,但是,我感觉有点搓,不太像是对单链表的操作,我想如果是面试中的话,这也不会是面试官想要的答案,所以,换个方法想想,有没有高大上一点的方法,我并不是觉得应该在面试中让解题方法花哨一点,但是如果可以让面试官眼前一亮的话,我相信没人会拒绝的吧,那么接下来,我们就是是前后指针来求解,
既然是倒数第k个结点,那么我们让一个指针front走在前面,先走k个结点,然后再定义一个指针back走在后面,那么font和back之间的距离就是k, 当front指向最后一个节点时,back指向的就是倒数第k个结点,这样的话是不是就简单多了;
代码实现时的注意:
要注意循环的终止条件;
要注意循环结束后最K进行判断的条件,这些都需要自己不断的举例,不断的推敲,写出鲁棒性好的代码!
要注意k是非尾结点,且小于单链表的长度;(千万不要忘记)
要注意循环结束后最K进行判断的条件,这些都需要自己不断的举例,不断的推敲,写出鲁棒性好的代码!
要注意k是非尾结点,且小于单链表的长度;(千万不要忘记)
算法实现:
//删除链表的倒数第k个结点;1<k<链表总长度
void DelKNod(pLinkList pList,int k)
{
pLinkNode front = NULL;//走在前面的指针
pLinkNode back = NULL;//走在后面的指针
pLinkNode tmp = NULL;//临时指针
assert(pList);
front = back = pList ->pHead ;//都初始化为指向第一个元素
if(front == NULL)//如果是空链表则返回
return ;
while(front->next )//当前面的指针指向最后一个结点则跳出循环
{
k--;
if(k<=0)//当走到正数第k个结点,则后面的指针开始移动
{
back = back->next ;
}
front = front->next ;
}
if(k<=1)//注意这里if的判定条件
{
//两种删除方式,一种是直接调用以前讲过的一个操作函数,删除一个非尾结点;
//EraseNotTail(back);
//一种是交换倒数第k个元素和它后一个元素的data,注意k是非尾结点!
back->data = back->next ->data ;
tmp = back->next ;
back->next = back->next ->next ;
free(tmp);
tmp = NULL;
}
}
未完待续!