

>KMP字符串比较算法#include <iostream>
using namespace std;
// 定义链表节点结构体
typedef struct LNode
{
int data; // 节点数据
struct LNode *next; // 指向下一个节点的指针
} LNode, *LinkList; // LinkList为指向LNode的指针类型
// 头插法插入节点
void HeadInsert(LinkList &L)
{
int val = 0;
// 读取输入直到遇到换行
while (cin >> val)
{
LNode *s = new LNode; // 创建新节点
s->data = val; // 将输入值赋给新节点
s->next = L->next; // 新节点指向当前头节点的下一个节点
L->next = s; // 将头节点的next指向新节点
// 如果遇到换行,停止输入
if (cin.get() == '\n')
{
break;
}
}
}
// 尾插法插入节点
void TailInsert(LinkList &L)
{
int val = 0;
LNode *r = L; // r指向链表的尾部
// 读取输入直到遇到换行
while (cin >> val)
{
LNode *s = new LNode; // 创建新节点
s->data = val; // 将输入值赋给新节点
r->next = s; // 将尾节点的next指向新节点
r = s; // 更新r为新节点
r->next = NULL; // 新节点的next指向NULL
// 如果遇到换行,停止输入
if (cin.get() == '\n')
{
break;
}
}
}
// 遍历输出链表元素
void Print(LinkList L)
{
LNode *p = L->next; // 从第一个节点开始遍历
while (p)
{
cout << p->data << '\t'; // 输出节点数据
p = p->next; // 移动到下一个节点
}
cout << endl; // 输出换行
}
// 判断链表LB是否为链表LA的子序列
void SubNode(LinkList &LA, LinkList &LB)
{
LNode *p, *q, *pre; // LA、LB的工作节点和前一个节点
p = LA->next; // p指向LA的第一个节点
q = LB->next; // q指向LB的第一个节点
pre = p; // pre指向p的初始位置
while (p && q)
{
// 如果两个节点的值相等,继续比较下一个节点
if (p->data == q->data)
{
p = p->next; // 移动p指针
q = q->next; // 移动q指针
}
// 如果不相等,pre向后移动一位,q重新开始
else
{
pre = pre->next; // pre指向下一个节点
p = pre; // 更新p指针
q = LB->next; // 重新开始比较LB的链表
}
}
// 如果q没有到达链表尾部,说明LB不是LA的子序列
if (q)
{
cout << "B不是A的子序列" << endl;
return; // 结束函数
}
// 如果q到达链表尾部,说明LB是LA的子序列
cout << "B是A的子序列" << endl;
}
// 主函数
int main()
{
LinkList LA = new LNode; // 创建链表A的头节点
LinkList LB = new LNode; // 创建链表B的头节点
// 通过尾插法输入链表元素
TailInsert(LA);
TailInsert(LB);
// 判断LB是否为LA的子序列
SubNode(LA, LB);
return 0; // 程序结束
}
>定义两个工作指针,一个从前向后扫描
>一个从后向前扫描#include <iostream>
using namespace std;
// 定义双向循环链表的节点结构体
typedef struct LNode
{
int data; // 节点存储的数据
struct LNode *prior; // 指向前驱节点的指针
struct LNode *next; // 指向后继节点的指针
} LNode, *LinkList; // LinkList为指向LNode的指针类型
// 尾插法插入节点
void TailInsert(LinkList &L)
{
int val = 0; // 用于存储输入的值
LNode *r = L; // r指向链表的当前尾节点
while (cin >> val) // 循环读取输入
{
LNode *s = new LNode; // 创建新节点
s->data = val; // 将输入值赋给新节点
r->next = s; // 将当前尾节点的next指向新节点
s->prior = r; // 新节点的prior指向当前尾节点
r = s; // 更新r为新节点
// 如果遇到换行,停止输入
if (cin.get() == '\n')
{
break; // 结束输入
}
}
// 形成循环链表,将新尾节点的next指向头节点L
r->next = L; // 尾节点指向头节点
L->prior = r; // 头节点的prior指向尾节点
}
// 遍历输出链表元素
void Print(LinkList L)
{
LNode *p = L->next; // 从头节点的下一个节点开始遍历
while (p != L) // 当未回到头节点时继续
{
cout << p->data << '\t'; // 输出节点数据
p = p->next; // 移动到下一个节点
}
cout << endl; // 输出换行
}
// 判断循环链表是否对称
void JudgeSymmetry(LinkList &L)
{
LNode *p, *q; // 定义工作节点,p指向头节点的下一个,q指向头节点的前驱
p = L->next; // p指向第一个数据节点
q = L->prior; // q指向最后一个数据节点
// 当p和q未重合时继续判断
while (p != q)
{
// 偶数元素情况
if (p->next == q && p->data == q->data)
{
cout << "该循环链表对称" << endl; // 若p和q相遇且数据相等
return; // 返回
}
// 奇数情况
if (p->data != q->data)
{
cout << "该循环链表不对称" << endl; // 若数据不相等,链表不对称
return; // 返回
}
else
{
p = p->next; // p向后移动一位
q = q->prior; // q向前移动一位
}
}
cout << "该循环链表对称" << endl; // 若p和q重合,链表对称
}
// 主函数
int main()
{
LinkList L = new LNode; // 创建一个链表的头节点
TailInsert(L); // 通过尾插法插入节点
Print(L); // 打印链表中的元素
JudgeSymmetry(L); // 判断链表是否对称
}
>问题关键就是找到两个链表的尾指针
>然后修改指针指向#include <iostream>
using namespace std;
// 定义链表节点结构体
typedef struct LNode
{
int data; // 节点存储的数据
struct LNode *next; // 指向下一个节点的指针
} LNode, *LinkList; // LinkList为指向LNode的指针类型
// 尾插法插入节点
void TailInsert(LinkList &L)
{
int val = 0; // 用于存储输入的值
LNode *r = L; // r指向链表的当前尾节点
while (cin >> val) // 循环读取输入
{
LNode *s = new LNode; // 创建新节点
s->data = val; // 将输入值赋给新节点
r->next = s; // 将当前尾节点的next指向新节点
r = s; // 更新r为新节点
// 如果遇到换行,停止输入
if (cin.get() == '\n')
{
break; // 结束输入
}
}
r->next = L; // 尾节点指向头节点,形成循环链表
}
// 遍历输出链表元素
void Print(LinkList L)
{
LNode *p = L->next; // 从头节点的下一个节点开始遍历
while (p != L) // 当未回到头节点时继续
{
cout << p->data << '\t'; // 输出节点数据
p = p->next; // 移动到下一个节点
}
cout << endl; // 输出换行
}
// 连接两个循环链表
void ConnectList(LinkList &LA, LinkList &LB)
{
LNode *pa, *pb; // 定义两个工作指针
pa = LA->next; // pa指向LA的第一个数据节点
pb = LB->next; // pb指向LB的第一个数据节点
// 找到LA的尾指针
while (pa->next != LA) // 当pa未到达尾节点时
{
pa = pa->next; // 移动pa指针
}
// 找到LB的尾指针
while (pb->next != LB) // 当pb未到达尾节点时
{
pb = pb->next; // 移动pb指针
}
// 修改指针指向
pa->next = LB->next; // 将LA的尾节点指向LB的第一个数据节点
pb->next = LA; // 将LB的尾节点指向LA的头节点
}
// 主函数
int main()
{
LinkList LA = new LNode; // 创建一个链表LA的头节点
LinkList LB = new LNode; // 创建一个链表LB的头节点
TailInsert(LA); // 通过尾插法插入LA的节点
TailInsert(LB); // 通过尾插法插入LB的节点
ConnectList(LA, LB); // 连接两个循环链表LA和LB
Print(LA); // 打印链表LA中的元素
}
>定义几个工作指针
>每次遍历找到最小值将其删除
>直到表为空#include <iostream>
using namespace std;
// 定义链表节点结构体
typedef struct LNode
{
int data; // 节点存储的数据
struct LNode *next; // 指向下一个节点的指针
} LNode, *LinkList; // LinkList为指向LNode的指针类型
// 尾插法插入节点
void TailInsert(LinkList &L)
{
int val = 0; // 用于存储输入的值
LNode *r = L; // r指向链表的当前尾节点
while (cin >> val) // 循环读取输入
{
LNode *s = new LNode; // 创建新节点
s->data = val; // 将输入值赋给新节点
r->next = s; // 将当前尾节点的next指向新节点
r = s; // 更新r为新节点
// 如果遇到换行,停止输入
if (cin.get() == '\n')
{
break; // 结束输入
}
}
r->next = L; // 尾节点指向头节点,形成循环链表
}
// 遍历输出链表元素
void Print(LinkList L)
{
LNode *p = L->next; // 从头节点的下一个节点开始遍历
while (p != L) // 当未回到头节点时继续
{
cout << p->data << '\t'; // 输出节点数据
p = p->next; // 移动到下一个节点
}
cout << endl; // 输出换行
}
// 删除链表中的最小值
void DelValue(LinkList &L)
{
LNode *p, *pre, *minP, *minPre; // 定义工作节点和保存最小值及其前驱的指针
// 只要链表不为空,就搜索最小值
while (L->next != L)
{
// 重置指针
p = minP = L->next; // p指向第一个数据节点,minP也指向第一个
pre = minPre = L; // pre指向头节点,minPre也指向头节点
while (p != L) // 遍历链表
{
// 找到更小的值
if (p->data < minP->data)
{
minP = p; // 更新最小值节点
minPre = pre; // 更新最小值节点的前驱
}
pre = p; // 更新前驱指针
p = p->next; // 移动到下一个节点
}
// 输出并删除最小值
cout << minP->data << '\t'; // 输出最小值
minPre->next = minP->next; // 删除最小值节点
delete minP; // 释放内存
}
delete L; // 删除头节点
}
// 主函数
int main()
{
LinkList L = new LNode; // 创建一个链表的头节点
TailInsert(L); // 通过尾插法插入节点
DelValue(L); // 删除链表中的最小值
}
>不要被其复杂度吓到了;其实也就那样;freq 就是查找+1嘛然后按序递减
>双链表的插入、删除#include <iostream>
using namespace std;
// 定义链表节点结构体
typedef struct LNode
{
int data; // 节点存储的数据
int freq = 0; // 节点访问频率
struct LNode *pred; // 指向前驱节点的指针
struct LNode *next; // 指向后继节点的指针
} LNode, *LinkList; // LinkList为指向LNode的指针类型
// 尾插法插入节点
void TailInsert(LinkList &L)
{
int val = 0; // 用于存储输入的值
LNode *r = L; // r指向链表的当前尾节点
while (cin >> val) // 循环读取输入
{
LNode *s = new LNode; // 创建新节点
s->data = val; // 将输入值赋给新节点
r->next = s; // 将当前尾节点的next指向新节点
s->pred = r; // 设置新节点的前驱为当前尾节点
r = s; // 更新r为新节点
// 如果遇到换行,停止输入
if (cin.get() == '\n')
{
break; // 结束输入
}
}
r->next = L; // 尾节点指向头节点,形成循环链表
L->pred = r; // 头节点的前驱指向尾节点
}
// 遍历输出链表元素
void Print(LinkList L)
{
LNode *p = L->next; // 从头节点的下一个节点开始遍历
while (p != L) // 当未回到头节点时继续
{
cout << p->data << '\t'; // 输出节点数据
p = p->next; // 移动到下一个节点
}
cout << endl; // 输出换行
}
// 查找节点并更新频率
LNode *Locate(LinkList &L, int x)
{
LNode *p, *q;
p = L->next; // 从头节点的下一个节点开始查找
// 查找数据为x的节点
while (p && p->data != x)
{
p = p->next; // 移动到下一个节点
}
if (!p) // 如果未找到,返回NULL
{
return NULL;
}
else
{
p->freq++; // 找到节点,增加访问频率
// 如果当前节点是头节点的下一个节点,或者其前驱的频率大于当前频率
if (p->pred == L || p->pred->freq > p->freq)
{
return p; // 返回当前节点
}
// 如果有后继节点,更新其前驱
if (p->next != NULL)
{
p->next->pred = p->pred; // 更新后继节点的前驱指向当前节点的前驱
}
p->pred->next = p->next; // 更新前驱节点的后继指向当前节点的后继
q = p->pred; // q指向当前节点的前驱
// 在前驱节点中寻找合适的位置插入当前节点
while (q != L && q->freq <= p->freq)
{
q = q->pred; // 向前遍历,寻找更高频率的节点
}
// 插入当前节点到新位置
p->next = q->next; // 更新当前节点的后继
if (q->next != NULL)
{
q->next->pred = p; // 更新后继节点的前驱
}
p->pred = q; // 更新当前节点的前驱
q->next = p; // 将当前节点插入到前驱节点的后继
}
return p; // 返回当前节点
}
// 主函数
int main()
{
LinkList L = new LNode; // 创建一个链表的头节点
TailInsert(L); // 通过尾插法插入节点
LNode *p = Locate(L, 3); // 查找值为3的节点
}