// // main.cpp // test_list_oper // // Created by Hugo Cao on 15/7/6. // Copyright (c) 2015年 Hugo Cao . All rights reserved. // /* 题目: 输出链表中倒数第k个节点, 输入一个链表,输出链表中倒数第K个节点,为了符合大多数人的习惯,本题从1开始计数, 即链表的尾节点是倒数第一个是1节点,例如输入一个6个节点, 从头节点开始,依次是1,2,3,4,5,6。倒数第三个节点是4. 解题思路: (1) 最简单的方式,遍历一遍,然后计算倒数第k个位 n-k+1 (2) 第二种方式,只遍历一次,用空间代替时间,设置第二个指针,让一个指针先出发, 由于输出倒数第K个,所以,输出位置是n - k + 1.所以当前一个节点,走了K-1时,第二个出发。 引申:这个问题,提示了一个很好的解决问题的方式,也是空间换时间很好的例证。 (1)比如打印单链表中间的那个元素,依旧可以设置2个指针,让一个快一个慢,一个一次走1步,另一个走2步。 (2)判断一个链表是否是循环链表,依旧可以设置一个快指针,一个慢指针,判断是否能追上另一个,如果可以追上,就是循环列表。 */ #include <stdio.h> #include <stdlib.h> #include <stack> #include <iostream> using namespace std; typedef struct ListNode { int m_nValue; struct ListNode *m_pNext; } lNode; //添加元素结点 void listAddNode(lNode *head) { lNode *p = head, *p_Inter = NULL; if (!(p_Inter = ((lNode *)malloc(sizeof(lNode))))) { printf("the memery is don't create it "); return; } p_Inter->m_pNext = NULL; int data; printf("请输入数字: "); scanf("%d", &data); p_Inter->m_nValue = data; while (p->m_pNext != NULL) { p = p->m_pNext; } p->m_pNext = p_Inter; } //创建元素结点 lNode* createList(lNode *head) { if (!(head = ((lNode *)malloc(sizeof(lNode))))) { printf("the memery is don't create it "); return NULL; } head->m_pNext = NULL; int data; printf("请输入数字: "); scanf("%d", &data); head->m_nValue = data; lNode *p = head; char X_cin = 'Y'; while (true) { printf("是否继续添加:N/n "); cin >> X_cin; if (X_cin == 'y' || X_cin == 'Y') { ; } else if (X_cin == 'N' || X_cin == 'n') { return head; } else { ; } listAddNode(p); } } //显示列表 void showList(lNode *head) { if (NULL == head) { cout << "list is empty " << endl; return; } lNode *p = head; while (p != NULL) { printf("%d ", p->m_nValue); p = p->m_pNext; } } //翻转链表 void reversePut(lNode *point) { stack <int> stack_rev; lNode *p = point; while (p != NULL) { stack_rev.push(p->m_nValue); p = p->m_pNext; } cout << "翻转以后的输出" << endl; while (!stack_rev.empty()) { cout << stack_rev.top() << endl; stack_rev.pop(); } } //输出倒数第K个元素节点,遍历所有节点型。 void firstPrintNode(lNode *head, int kNum) { if (head == NULL || kNum <= 0) return; int length = 0; lNode *p = head; while (p != NULL) { p = p->m_pNext; length++; } if (length < kNum) { cout << "链表长度为:" << length << ", 而遍历的节点位置是: "<< kNum << endl; return; } cout << "链表长度为:" << length; p = head; while (length != kNum) { length--; p = p->m_pNext; } cout << " 输出倒数第K个元素节点: " << p->m_nValue << endl; } //输出第K个结点,第二种方式,两个指针 void secondPrintNode(lNode *head, int kNum) { if (head == NULL || kNum <= 0) return; lNode *p1 = head; lNode *p2 = head; int length = kNum; while (p1 != NULL) { p1 = p1->m_pNext; length--; if (length < 0) p2 = p2->m_pNext; } cout << " 输出倒数第K个元素节点: " << p2->m_nValue << endl; } int main() { lNode *head = NULL; head = createList(head); showList(head); //翻转链表 //reversePut(head); secondPrintNode(head, 3); return 0; }