如何找出单链表中的倒数第k个元素

来源:互联网 发布:算法第四版课后题答案 编辑:程序博客网 时间:2024/06/09 18:46

如何找出单链表中的倒数第k个元素
(1)方法1:首先遍历一遍单链表,求出整个单链表的长度n,然后将倒数第k个,转换为正数第n-k个,接下去遍历一次就可以得到结果。但该算法需要对链表进行两次遍历,第一次遍历用于求解单链表的长度,第二次遍历用于查找正数第n-k个元素。
(2)方法2:如果沿着从头到尾的方向,从链表中的某个元素开始,遍历k个元素后刚好达到链表尾,那么该元素就是要找的倒数第k个元素。根据这一性质,可以设计如下算法:从头节点开始,一次对链表的每一个节点元素进行这样的测试,遍历k个元素,查看是否到达链表尾,直到找到那个倒数第k个元素为止。这种方法将对同一批元素进行反复多次的遍历,对于链表中的大部分元素而言,都要遍历k个元素,如果链表的长度为n,该算法的时间复杂度为O(kn)级,效率太低。
(3)方法3:有一种更高效的方式,只需要一次遍历即可查找到倒数第k个元素。由于单链表只能从头到尾依次访问链表的各个节点,所以如果要找链表的倒数第k个元素,也只能从头到尾进行遍历查找。在查找过程中,设置两个指针,让其中一个指针比另一个指针先前移k-1步,然后两个指针同时往前移动。循环直到先行的指针指为NULL时,另一个指针所指的位置就是所要找的位置。如下所示:

#include <stdio.h>#include <stdlib.h>typedef struct node{    int data;    struct node *next;} NODE;// 尾插法创建单链表(带头节点)NODE *createEnd(int arr[], int len){    NODE *head = (NODE *)malloc(sizeof(NODE)); // 生成头节点    head->next = NULL;    NODE *end = head;  // 尾指针初始化    for (int i = 0; i < len; i++) {        NODE *p = (NODE *)malloc(sizeof(NODE)); // 为每个数组元素建立一个节点        p->data = arr[i];        end->next = p;  // 将节点p插入到终端节点之后        end = p;    }    end->next = NULL;  // 单链表建立完毕,将终端节点的指针域置空    return head;}// 找出单链表中的倒数第k个元素NODE *search_last_k(NODE *head, int k){    NODE *p1 = head;    NODE *p2 = head;    for (int i = 0; i < k; i++) {        p2 = p2->next;    }    while (p2 != NULL) {        p1 = p1->next;        p2 = p2->next;    }    return p1;}// 单链表打印void print(NODE *head){    if (head == NULL) return;    NODE *p = head->next;    while (p != NULL) {        printf("%d\n", p->data);        p = p->next;    }}int main(void){    int arr[] = {1,2,3,4,5,6,7};    int len = sizeof(arr)/sizeof(int);    NODE *head = createEnd(arr, len);    print(head);    printf("-----------\n");    NODE *temp_k = search_last_k(head, 3);    printf("%d\n",temp_k->data);    return 0;}
1 0