求链表中倒数第k个结点
题目:输入一个单向链表,输出该链表中倒数第k个结点。链表的倒数第0个结点为链表的尾指针。
更优化的算法,第二个指针每次移动k步而不是一步,减少遍历的次数!
//将链表中的每k个节点作为一组处理,
//倒数第k个元素只能出现在最后一组, (节点的个数是k的整数倍时)
//或者倒数第二组,(节点的个数不是 k的整数倍时)
node_t * findKthTailNode(node_t *head, int k) {
int i;
int j;
node_t *pre;
node_t *p;
node_t *q;
if(head == NULL || k==0) return NULL; //链表为空
pre = NULL;
p = head;
q = p;
//将链表中的每k个节点作为一组处理,
//倒数第k个元素只能出现在最后一组, (节点的个数是k的整数倍时)
//或者倒数第二组,(节点的个数不是 k的整数倍时)
while(q) {
for(i=0; i<k-1; ) {
if(q) {
q = q->next;
if(q) ++i; //组内节点移动的个数
}
else {
break;
}
}
if(q) {
pre = p;
p = q->next;
q = p;
}
}
if(p){//节点的个数不是k的整数倍时。
pre = pre->next;
for(j=0; j<i; ) {
pre = pre->next;
++j;
}
}
return pre;
}
实现代码如下:
#include <stdio.h>
#include <stdlib.h>
typedef char item_t;
typedef struct node {
item_t item;
struct node * next;
} node_t;
//typedef node_t * List_t;
node_t * findKthTailNode(node_t *head, int k);
int main()
{
node_t * head = NULL;
node_t * tmp;
//构建链表
int i=0;
do{
tmp = (node_t *) malloc(sizeof(node_t));
tmp->item = 'a' + i;
tmp->next = head;
head = tmp;
}while(++i<26);
//显示链表
node_t *p = head;
while(p){
printf("%c ", p->item);
p = p->next;
}
printf("\n");
//测试函数
for(i=0; i<27; i++){
printf("%d: ", i);
p = findKthTailNode(head, i);
while(p){
printf("%c ", p->item);
p = p->next;
}
printf("\n");
}
return 0;
}
node_t * findKthTailNode(node_t *head, int k) {
int i;
int j;
node_t *pre;
node_t *p;
node_t *q;
if(head == NULL || k==0) return NULL; //链表为空
pre = NULL;
p = head;
q = p;
//将链表中的每k个节点作为一组处理,
//倒数第k个元素只能出现在最后一组, (节点的个数是k的整数倍时)
//或者倒数第二组,(节点的个数不是 k的整数倍时)
while(q) {
for(i=0; i<k-1; ) {
if(q) {
q = q->next;
if(q) ++i; //组内节点移动的个数
}
else {
break;
}
}
if(q) {
pre = p;
p = q->next;
q = p;
}
}
if(p){//节点的个数不是k的整数倍时。
pre = pre->next;
for(j=0; j<i; ) {
pre = pre->next;
++j;
}
}
return pre;
}
用Linux下的valgrind 工具的memcheck功能检查的到的内存泄露的结果如下:(未对动态分配的(malloc)进行释放(free)造成的)
version 2 :驱动测试程序中,未对链表进行释放,完善版本。
#include <stdio.h>
#include <stdlib.h>
typedef char item_t;
typedef struct node {
item_t item;
struct node * next;
} node_t;
//typedef node_t * List_t;
node_t * findKthTailNode(node_t *head, int k);
int main()
{
node_t * head = NULL;
node_t * tmp;
int len;
//构建链表
int i=0;
do{
tmp = (node_t *) malloc(sizeof(node_t));
tmp->item = '1' + i;
tmp->next = head;
head = tmp;
}while((++i+ '1')^128); //while(++i<79);
// printf("%d \n", tmp->item);
len = i+1;
//显示链表
node_t *p = head;
while(p){
printf("%c ", p->item);
p = p->next;
}
printf("\n");
//测试函数
for(i=0; i<len; i++){
printf("%d: ", i);
p = findKthTailNode(head, i);
while(p){
printf("%c ", p->item);
p = p->next;
}
printf("\n");
}
//释放链表
while(head) {
p = head;
head = p->next;
free(p);
}
/*
//显示链表
p = head;
while(p){
printf("%c ", p->item);
p = p->next;
}
printf("\n");
*/
return 0;
}
node_t * findKthTailNode(node_t *head, int k) {
int i;
int j;
node_t *pre;
node_t *p;
node_t *q;
if(head == NULL || k==0) return NULL; //链表为空
pre = NULL;
p = head;
q = p;
//将链表中的每k个节点作为一组处理,
//倒数第k个元素只能出现在最后一组, (节点的个数是k的整数倍时)
//或者倒数第二组,(节点的个数不是 k的整数倍时)
while(q) {
for(i=0; i<k-1; ) {
if(q) {
q = q->next;
if(q) ++i; //组内节点移动的个数
}
else {
break;
}
}
if(q) {
pre = p;
p = q->next;
q = p;
}
}
if(p){//节点的个数不是k的整数倍时。
pre = pre->next;
for(j=0; j<i; ) {
pre = pre->next;
++j;
}
}
return pre;
}
加入链表的释放后的,valgrind工具的memcheck功能检测结果显示如下: