查找倒数第k个数
用尽可能快的方法返回带头节点单链表中倒数第 k 个结点的地址,如果不存在,则返回 NULL。
#include <iostream>
using namespace std;
typedef int datatype;
typedef struct ListNode {
datatype data;
struct ListNode *next;
}LNode,*LinkList;
/*创建一个非空的带头节点单链表 */
void CreatbyQueue(LinkList &L);
/*查找并返回带头节点单链表中倒数第k个节点,如果不存在,则返回NULL。*/
LNode* SearchKthToLast(LinkList L,int k);
/*查找并返回带头节点单链表中倒数第k个节点,如果不存在,则返回NULL。*/
LNode* SearchKthToLast(LinkList L,int k)
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
if (L == NULL || k <= 0) {
return NULL;
}
LNode *pAhead = L->next; // Start from the first actual data node
LNode *pBehind = L->next;
int count = 0;
// Move pAhead k nodes ahead
while (pAhead != NULL && count < k) {
pAhead = pAhead->next;
++count;
}
// If we didn't move k nodes ahead, k is larger than the length of the list
if (count < k) {
return NULL;
}
// Move pAhead and pBehind at the same pace
while (pAhead != NULL) {
pAhead = pAhead->next;
pBehind = pBehind->next;
}
// pBehind is now the kth to last node
return pBehind;
/********** End **********/
}
链表逆置
1、单链表的插入
2、单链表的删除
#include <iostream>
using namespace std;
typedef int datatype;
typedef struct ListNode {
datatype data;
struct ListNode *next;
}LNode,*LinkList;
/*单链表创建*/
void CreateList(LinkList &L);
/*其中L是用户传入的带头节点单链表的头指针,L是引用类型;函数Reverse将链表L逆置。*/
void Reverse( LinkList &L);
/*顺序输出链表每个结点,每个结点元素值以空格符间隔,以换行符结束。 */
void DispList(LinkList L);
/*其中L是用户传入的带头节点单链表的头指针,L是引用类型;函数Reverse将链表L逆置。*/
void Reverse( LinkList &L){
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode *current = L->next; // 指向第一个数据结点
LNode *prev = NULL; // 初始化前一个结点指针为 NULL
LNode *next = NULL; // 初始化下一个结点指针为 NULL
// 遍历链表,逐个结点逆置
while (current != NULL) {
next = current->next; // 保存下一个结点
current->next = prev; // 逆置当前结点的 next 指针
prev = current; // 前一个结点移动到当前结点
current = next; // 当前结点移动到下一个结点
}
// 最后,将头结点的 next 指针指向新的第一个结点(原来的最后一个结点)
L->next = prev;
/********** End **********/
}
有序单链表的就地合并
相关知识
单链表的存储;
单链表的基本操作。
#include <iostream>
using namespace std;
typedef int datatype;
typedef struct ListNode {
datatype data;
struct ListNode *next;
}LNode,*LinkList;
/*创建一个非空的带头节点单链表,默认输入数据是升序的。 */
void CreatbyQueue(LinkList &L);
/*已知两个带头节点的单链表L1和L2中的结点值均已按严格升序排序,
设计一个算法,将L1和L2就地合并成一个严格升序的带头节点单链表,合
并之后用L1记录新的带头节点单链表的头指针,L2单链表为空。 */
void MergeAscend(LinkList &L1,LinkList & L2);
/*顺序输出链表每个结点,每个结点元素值以逗号间隔,以换行符结束。 */
void DispList(LinkList L);
/*将L1和L2合并成一个升序的带头节点单链表,并用L1记录新的带头节点单链表的头指针;*/
void MergeAscend(LinkList &L1,LinkList &L2)
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LinkList R,P,Q,temp;
R=L1; //R指向表位
P=L1->next; // p指向L1
L1->next=NULL;
Q=L2->next; //Q point L1
L2->next=NULL;
while(P&&Q)
{
if(P->data<Q->data)
{
R->next=P;
R=P;
P=P->next;
}
else if(P->data>Q->data)
{
R->next=Q;
R=Q;
Q=Q->next;
}
else{
R->next=P;
R=P;
P=P->next;//两数相等
temp=Q;
Q=Q->next;
delete temp;
}
}
if(P) R->next=P;
if(Q) R->next=Q;
/********** End **********/
}
两个一元多项式异地相加
利用带头节点单链表实现一元稀疏多项式的加法运算(C=A+B),实现异地相加,A,B 保持不变。
#include <iostream>
using namespace std;
typedef struct Node
{
int coef; //系数
int expo; //指数
} datatype; //表示多项式的一项
typedef struct ListNode
{
datatype data;
struct ListNode *next;
} LNode,*LinkList;
bool InitList(LinkList &L);//初始化一个为空的带头结点单链表
/*创建一个非空的带头节点单链表,默认输入数据是升序的。 */
void CreatbyQueue(LinkList &L);
/*实现多项式加法C=A+B,A和B保持不变*/
void Add(LinkList &A,LinkList &B,LinkList &C);
/*顺序输出链表每个结点,每个结点元素值以逗号间隔,以换行符结束。 */
void DispList(LinkList L);
/*实现多项式加法C=A+B,A和B保持不变*/
void Add(LinkList &A,LinkList &B,LinkList &C)
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode *pa = A->next; // 指向链表 A 的第一个数据节点
LNode *pb = B->next; // 指向链表 B 的第一个数据节点
LNode *pc = C = new LNode; // 创建结果链表 C 的头节点,并让 pc 指向它
pc->next = NULL;
// 遍历链表 A 和 B
while (pa != NULL && pb != NULL) {
if (pa->data.expo < pb->data.expo) { // 如果 A 的指数小于 B 的指数
pc->next = new LNode; // 在 C 中创建一个新的节点
pc = pc->next;
pc->data = pa->data; // 将 A 的当前节点数据复制到 C
pa = pa->next; // A 指针后移
} else if (pa->data.expo > pb->data.expo) { // 如果 A 的指数大于 B 的指数
pc->next = new LNode; // 在 C 中创建一个新的节点
pc = pc->next;
pc->data = pb->data; // 将 B 的当前节点数据复制到 C
pb = pb->next; // B 指针后移
} else { // 如果 A 和 B 的指数相等
int sum = pa->data.coef + pb->data.coef; // 将系数相加
if (sum != 0) { // 如果系数不为 0,则添加到结果链表 C
pc->next = new LNode;
pc = pc->next;
pc->data.coef = sum;
pc->data.expo = pa->data.expo;
}
pa = pa->next; // A 指针后移
pb = pb->next; // B 指针后移
}
}
// 将剩余的 A 或 B 的节点添加到 C
while (pa != NULL) {
pc->next = new LNode;
pc = pc->next;
pc->data = pa->data;
pa = pa->next;
}
while (pb != NULL) {
pc->next = new LNode;
pc = pc->next;
pc->data = pb->data;
pb = pb->next;
}
pc->next = NULL; // 确保结果链表的最后一个节点的 next 指针为 NULL
/********** End **********/
}
约瑟夫环问题
约瑟夫环问题的描述是:编号为 1,2,…,n 的n 个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限m,从第一个人开始按顺时针方向自1开始顺序报数,报到 m 时停止报数。报 m 的人出列,将他的密码作为一个新的 m 值,从他在顺时针方向上的下一个人开始重新从 1 报数,如此下去,直至所有人全部出列为止。请设计一个程序求出列顺序。
#include<iostream>
using namespace std;
#define ERROR NULL
typedef struct Node
{
int n; //个人的编号
int m; //手中的密码
} ElemType; //ElemType 定义为结构体类型,分别记录每个人的编号以及手中的密码
typedef struct LNode
{
ElemType data; //结点的数据域
struct LNode *next; //结点的指针域
} LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
//初始化一个空的循环单链表
bool InitList(LinkList &L);
//创建元素个数为N的循环单链表L,输入数据以空格分隔
void CreateCircularList( LinkList &L,int N );
/*顺序输出链表每个结点,注意循环链表遍历结束的判断,每个结点元素值以逗号间隔, 元素内格式为(n m) ,以换行符结束。 */
void DispList(LinkList L);
/*
约瑟夫环Josephus(循环单链表、无头结点)
编号为1,2,…,n的n个人按顺时针方向围坐一圈,
每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限m,
从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为一个新的m值,
从他在顺时针方向上的下一个人开始重新从1报数
,如此下去,直至所有人全部出列为止。
*/
void Josephus(LinkList &L,int M);
//创建元素个数为N的循环单链表L,输入数据以空格分隔
void CreateCircularList( LinkList &L,int N )
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
int i,m;
LNode *p,*r;//r用来只想循环单链表的表尾
for(i=1;i<=N;i++)
{
cin>>m;
p=new LNode;
p->data.m=m;
p->data.n=i;
if(L==NULL)//循环单链表为空
{
L=p;
L->next=L;//只有一个元素,既是表头也是表尾
r=L;
}
else//否则将p结点插入表尾,此时p的后继就是单链表的首结点即所指向结点,p编程新的表尾
{
p->next=L;
r->next=p;
r=p;
}
}
/********** End **********/
}
/*
约瑟夫环Josephus(循环单链表、无头结点)
编号为1,2,…,n的n个人按顺时针方向围坐一圈,
每人持有一个密码(正整数)。
一开始任选一个正整数作为报数上限m,
从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。
报m的人出列,将他的密码作为一个新的m值,
从他在顺时针方向上的下一个人开始重新从1报数
,如此下去,直至所有人全部出列为止。
*/
void Josephus(LinkList &L,int M)
{
// 请在这里补充代码,完成本关任务
/********** Begin *********/
LNode *p=L,*pre;//指向当前节点
int i;
pre=L;
while(pre->next!=L){
pre=pre->next; //找到首结点的前驱结点
}
while(p)
{
for(i=1;i<M;i++)
{
pre=p;
p=p->next;
}
cout<<" "<<p->data.n;
M=p->data.m; //使用新的密码M作为下一轮的密码
if(p->next!=p)
{
pre->next=p->next;// 将p结点从链表中删除
delete p;
p=pre->next;
}
else{
delete p;
p=NULL;
}
}
L=NULL;
/********** End **********/
}