1. 单链表小结腾讯面试题
题目:快速找到未知长度单链表的中间节点。
普通的方法很简单,首先遍历一遍单链表以确定单链表的长度L。然后再次从头节点出发循环L/2次找到单链表的中间节点。算法复杂度为:O(L+L/2)=O(3L/2)。
但是有一个很巧妙的方法:利用快慢指针!
利用快慢指针原理:设置两个指针search、mid都指向单链表的头节点。其中 search的移动速度是mid的2倍。当*search指向末尾节点的时候,mid正好就在中间了。这也是标尺的思想。我们来看下代码实现:
bool GetMidNode(LinkList L, DataType* e){LinkList search, mid;mid = search = L;while (search->next != NULL){//search移动的速度是 mid 的2倍if (search->next->next != NULL){search = search->next->next;mid = mid->next;}else{search = search->next;}}*e = mid->data;return true;}
//写一个完整的程序,实现随机生成20个元素的链表(尾插法或头插法任意),用我们刚才学到的方法快速查找中间结点的值并显示。
GetMidNode2.c
2. 判断单链表中是否有环

方法一:使用p、q两个指针,p总是向前走,但q每次都从头开始走,对于每个节点,看p走的步数是否和q一样。如图,当p从6走到3时,用了6步,此时若q从head出发,则只需两步就到3,因而步数不等,出现矛盾,存在环。
方法二:使用p、q两个指针,p每次向前走一步,q每次向前走两步,若在某个时候p == q,则存在环。
// 比较步数的方法int HasLoop1(LinkList L){LinkList cur1 = L; // 定义结点 cur1int pos1 = 0; // cur1 的步数while (cur1){ // cur1 结点存在LinkList cur2 = L; // 定义结点 cur2int pos2 = 0; // cur2 的步数while (cur2){ // cur2 结点不为空if (cur2 == cur1){ // 当cur1与cur2到达相同结点时if (pos1 == pos2) // 走过的步数一样break; // 说明没有环else // 否则{printf("环的位置在第%d个结点处。\n\n", pos2);return 1; // 有环并返回1}}cur2 = cur2->next; // 如果没发现环,继续下一个结点pos2++; // cur2 步数自增}cur1 = cur1->next; // cur1继续向后一个结点pos1++; // cur1 步数自增}return 0;}// 利用快慢指针的方法int HasLoop2(LinkList L){int step1 = 1;int step2 = 2;LinkList p = L;LinkList q = L;while (p != NULL && q != NULL && q->next != NULL){p = p->next;if (q->next != NULL)q = q->next->next;printf("p:%d, q:%d \n", p->data, q->data);if (p == q)return 1;}return 0;}
3.双向循环链表实践
课堂演示题目:
要求实现用户输入一个数使得26个字母的排列发生变化,例如用户输入3,
输出结果:DEFGHIJKLMNOPQRSTUVWXYZABC
同时需要支持负数,例如用户输入-3,
输出结果:XYZABCDEFGHIJKLMNOPQRSTUVW
#include<stdio.h>#include<stdlib.h>#define OK 1#define ERROR 0;typedef char ElemType;typedef int Status;typedef struct DualNode{ElemType data;struct DualNode* prior;struct DualNode* next;}DualNode, * DuLinkList;Status InitList(DuLinkList* L){DualNode* p, * q;int i;*L = (DuLinkList)malloc(sizeof(DualNode));if (!(*L)){return ERROR;}(*L)->next = (*L)->prior = NULL;p = (*L);for (i = 0; i < 26; i++){q = (DualNode*)malloc(sizeof(DualNode));if (!q){return ERROR;}q->data = 'A' + i;q->prior = p;q->next = p->next;p->next = q;p = q;}p->next = (*L)->next;(*L)->next->prior = p;return OK;}void caser(DuLinkList* L, int i){if (i > 0){do{(*L) = (*L)->next;} while (--i);}if (i < 0){i = i - 1;(*L) = (*L)->next;do{(*L) = (*L)->prior;} while (++i);}}int main(){DuLinkList L;int i, n;InitList(&L);printf("请输入一个整数:\n");scanf_s("%d", &n);printf("\n");caser(&L, n);for (i = 0; i < 26; i++){L = L->next;printf("%c", L->data);}printf("\n");return 0;}
Vigenere(维吉尼亚)加密:当输入明文,自动生成随机密匙匹配明文中每个字母并移位加密。
建议:当然你的随机密匙生成后不能丢掉,丢掉了就很难把明文还原来了,建议把随机密匙和密文加密存储在一起。
