求链表中倒数第k个结点

26 篇文章 0 订阅
15 篇文章 0 订阅

求链表中倒数第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)造成的)
Valgrind_test_result for version1

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功能检测结果显示如下:
findKthNode_result_tested_by_ valgrind




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值