数据结构与算法(上)线性表

理论部分:
1.卡特兰数的应用
出栈次序
一个栈(无穷大)的进栈序列为1,2,3,…,n,有多少个不同的出栈序列?
f(n)=h(n)= C(2n,n)/(n+1)= c(2n,n)-c(2n,n-1)

例如:
编号为1,2,3,4的四辆列车,顺序开进一个栈式结构的站台;则开出车站的顺序有__种可能。

枚举思路:
先进站的车可以先开,也可以后开。只有一种情况不可能:编号大的车开出后,比其编号小的车反序开出。也即编号大的车开出后,编号比其小的车只能由大到小依次开出(中间可以插入编号更大的车,但此车后面的编号小的车也要遵守此规则)。例如312的开出顺序是不可能的。对所有车进行全排列共有24种出法。但4开头的只能有一种:4321。所以少了3的全排列-1=5种。三开头的时候,必须先2后1开出,先1后2时4的位置有三种:3124、3142、3412,所以少了三种。1或2开头的时候,后面的车如果是4,则最后两辆必须是3、2或3、1。所以又少了1423、2413两种。总共少了5+3+2=10种,有24-10=14种开出法。

1 约瑟夫问题(Monkey king election)

描述
有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。

输入输入包含两个整数,第一个是n,第二个是m 1 < m,n<=300

输出输出包含一行,即最后猴王的编号。

样例输入12 4

样例输出1

//单循环链表解答
#include <iostream>
using namespace std;

struct monkey {
    int num;//号码
    monkey *next;//链表节点
};

int joseph(int sum,int cycle) {
    int i;
    monkey *cur, *nex, *head = NULL;

    head = new monkey;
    //此处创建一个循环链表
    head->num = 1;
    cur = head;
    for (i = 2; i <= sum; i++) {
        nex = new monkey;
        nex->num = i;
        cur->next = nex;
        cur = nex;
    }
    cur->next=head;

    cur = head;
    i = 1;
    //循环删除元素直到只剩下最后一个元素
    while (1) {
        nex = cur->next;
        i++;
        if (nex == cur)
            break;
        if ((i%cycle) == 0) {
            cur->next = nex->next;
            cur = cur->next;
            delete nex;
            i = 1;
        }
        else {
            cur = nex;
        }
    }
    return nex->num;
}

int main(void) {
    int n, m;
    cin >> n >> m;
    cout << joseph(n, m) << endl;
    return 0;
}


2 多项式加法

描述
我们经常遇到两多项式相加的情况,在这里,我们就需要用程序来模拟实现把 两个多项式相加到一起。首先,我们会有两个多项式,每个多项式是独立的一行,每个多项式由系数、幂数这样的多个整数对来表示。 如多项式2x20- x17+ 5x9- 7x7+ 16x5+ 10x4 + 22x2- 15 对应的表达式为:2 20 -1 17 5 9 - 7 7 16 5 10 4 22 2 -15 0。
为了标记每行多项式的结束,在表达式后面加上了一个幂数为负数的整数对。 同时输入表达式的幂数大小顺序是随机的。 我们需要做的就是把所给的两个多项式加起来。

输入输入包括多行。
第一行整数n,表示有多少组的多项式需要求和。(1< n < 100)
下面为2n行整数,每一行都是一个多项式的表达式。表示n组需要相加的多项式。
每行长度小于300。

输出输出包括n行,每行为1组多项式相加的结果。
在每一行的输出结果中,多项式的每一项用“[x y]” 形式的字符串表示,x是该项的系数、y是该项的幂数。要求按照每一项的幂从高到低排列,即先输出幂数高的项、再输出幂数低的项。
系数为零的项不要输出。

样例输入2
-1 17 2 20 5 9 -7 7 10 4 22 2 -15 0 16 5 0 -1
2 19 7 7 3 17 4 4 15 10 -10 5 13 2 -7 0 8 -8
-1 17 2 23 22 2 6 8 -4 7 -18 0 1 5 21 4 0 -1
12 7 -7 5 3 17 23 4 15 10 -10 5 13 5 2 19 9 -7

样例输出[ 2 20 ] [ 2 19 ] [ 2 17 ] [ 15 10 ] [ 5 9 ] [ 6 5 ] [ 14 4 ] [ 35 2 ] [ -22 0 ]
[ 2 23 ] [ 2 19 ] [ 2 17 ] [ 15 10 ] [ 6 8 ] [ 8 7 ] [ -3 5 ] [ 44 4 ] [ 22 2 ] [ -18 0 ]

#include <iostream>
using namespace std;

struct item {
    int k, ex;//系数,次数
    item *next;
};//单链表节点
item equalmark;

//用来在链表中查找ex与当前值相等的链表元素
item *search(item *current, item *head) {
    while (head->next != NULL) {
        if (current->ex == head->next->ex) {
            head->next->k += current->k;
            delete current;
            return &equalmark;
        }
        if (current->ex > head->next->ex)
            break;//current次数高于head下一项,把current插进head位
        head = head->next;
    }
    return head;
}

int main() {
    int inputnum;
    cin >> inputnum;
    while (inputnum--) {
        item *head = NULL, *current = NULL;
        int k, ex;
        for (int i = 0; i <= 1; i++) {//两行多项式
            while (cin >> k >> ex, ex >= 0) {
                current = new item;
                current->k=k, current->ex = ex, current->next = NULL;
                if (head == NULL)
                    head = current;
                else if (current->ex > head->ex) {//这其实是边输入边计算并按次数大到小排
                    current->next = head;
                    head = current;
                }//出现新的最高次项
                else if (current->ex == head->ex) {
                    (head->k)+=(current->k);
                    delete current;
                }//和head同次
                else {
                    item *temp = search(current, head);
                    if (temp != &equalmark) {
                        current->next = temp->next;//之前在这里犯了点小错..注意不是head而是temp,head传进函数但外面没变
                        temp->next = current;
                    }
                }
            }
        }
        current = head;

        //遍历加法之后得到的链表,输出结果
        while (current->next != NULL) {
            if (current->k != 0)
                cout << "[ " << current->k << ' ' << current->ex << " ] ";
            current = current->next;
        }
        if (current->k != 0)
            cout << "[ " << current->k <<' ' << current->ex << " ] "; 
        if (inputnum > 0)
                cout << endl;
        while (head != NULL) {
            item *temp = head->next;
            delete head;
            head = temp;
        }
    }
    return 0;

}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值