40.png

    1. /*
    2. 有一个带头结点的单链表,设计一个函数找到指定的倒数第k个节点,输出节点值,并返回1,否则返回0,前提不能改变链表,尽可能高效
    3. 分析:
    4. 我们可以先统计出总共的节点数count,那么该节点的顺序数num=count-k+1,当然如果k>count,直接返回0,时间复杂度为O(n)
    5. 这里还有另一种更加便捷的方法,只需对链表遍历一次,我们设立两个指针,最开始均指向首节点,然后让q先移动k个节点,之后p
    6. q同步移动,当q为NULL时,p所在的位置便是倒数第k个节点的位置
    7. */
    8. struct Link {
    9. int data;
    10. struct Link *next;
    11. };
    12. #define _CRT_SECURE_NO_WARNINGS
    13. #include <stdio.h>
    14. int findTheReciprocalK(Link *h,int k) {//这是第一种解法
    15. struct Link *p = h->next;
    16. int count = 0,num;
    17. while (p) {//统计元素个数
    18. count++;
    19. p = p->next;
    20. }
    21. p = h->next;
    22. if (k > count) {
    23. return 0;
    24. }
    25. else {
    26. num = count - k + 1;
    27. while (--num) {//这里要用--num,如果用num--,会导致p为下一个元素,注意
    28. p = p->next;
    29. }
    30. printf("%d",p->data);
    31. return 1;
    32. }
    33. }
    34. int findTheReciprocalK2(Link *h,int k) {//这是第二种解法
    35. struct Link *p = h->next, *q = h->next;
    36. int count = k;
    37. while (count--) {
    38. if (q==NULL) {
    39. printf("倒数第%d个节点不存在",k);
    40. return 0;
    41. }
    42. q = q->next;
    43. }
    44. while (q!=NULL) {
    45. p = p->next;
    46. q = q->next;
    47. }
    48. printf("倒数第%d个节点值为:%d",k,p->data);
    49. return 1;
    50. }
    51. int main() {
    52. int k;
    53. struct Link *head;
    54. Link *createLink(int);
    55. head = createLink(0);
    56. printf("请输入要查倒数第几个数:k=");
    57. scanf("%d",&k);
    58. //findTheReciprocalK(head,k);
    59. findTheReciprocalK2(head, k);
    60. return 0;
    61. }