链表的应用进阶操作

查找倒数第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 **********/  
   
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小狗碎碎念

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值