复习

线性表

#pragma once
template<class T>
class LinearList//线性表抽象基类
{
public:
    LinearList() {};                        //构造函数
    ~LinearList;                            //析构函数
    virtual int Size()const = 0;            //求表最大体积
    virtual int Length()const = 0;          //求表长度
    virtual int Search(T& x)const = 0;      //求给定x下表(搜索)
    virtual int Locate(int i)const = 0;     //定位第i个元素的位置
    virtual bool getDate(int i, T& x) = 0;  //求第i个表项的值
    virtual bool setDate(int i, T& x) = 0;  //修改第i个表项的值
    virtual bool Insert(int i, T& x) = 0;   //在第i个位置插入
    virtual bool Remove(int i, T& x) = 0;   //删除第i个位置的值
    virtual bool IsEmpty()const = 0;        //判断表空
    virtual bool IsFull()const = 0;         //判断表满
    virtual void Sort() = 0;                //排序
    virtual void input = 0;                 //输入
    virtual void output() = 0;              //输出
    virtual LinearList<T>operator=(LinearList<T>& L) = 0;//复制
};

线性表的结构特点:除第一及最后一个元素外,每个结点都只有一个前趋和只有一个后继。
表长:元素总个数n
空表:n=0
线性起点:a1
线性终点:an
下标:是元素的序号,表示元素在表中的位置
表头:第一个元素
表尾:最后一个元素

顺序表

优点:
⑴ 无需为表示表中元素之间的逻辑关系而增加额外的存储空间;
⑵ 随机存取:可以快速地存取表中任一位置的元素。
缺点:
⑴ 插入和删除操作需要移动大量元素;
⑵ 表的容量难以确定,表的容量难以扩充;
⑶ 造成存储空间的碎片。

// 顺序表.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include<stdlib.h>
#include"linearList.h"
using namespace std;
const int defaultSize = 100;

template<class T>
class SeqList :public LinearList<T>         //顺序表
{
protected:
    T* data;                                //存放数组
    int maxSize;                            //最大项数,项数!!!
    int last;                               //最后位置下标,初始化为-1
    void reSize(int newSize);               //改变数组大小
public:
    SeqList(int sz = defaultSize);
    SeqList(SeqList<T>& L);                 //复制构造函数
    ~SeqList() { delete[] data; }
    int Size()const { return maxSize; }     //最大可容纳表项个数,用const更加安全
    int Length()const { return last + 1; }  //计算表长度,const:不能改变数据成员的值,
                                            //const成员函数不能调用非const成员函数
    int Search(T& x)const;                  //搜索x在表中的位置,函数返回表项序号
    int Locate(int i)const;                 //搜索第i个表项,函数返回表项序号
    bool getData(int i, T& x)const          //取第i个表项的值,复制给x
    {
        if (i > 0 && i <= last + 1)
        {
            x = data[i - 1];
            return true;
        }
        else
            return false;
    }
    void setData(int i, T& x)               //修改第i个表项的值
    {
        if (i > 0 && i <= last + 1)data[i - 1] = x;
    }
    bool Insert(int i, T & x);              //用x来修饰第i个表项的值
    bool Remove(int, T & x);                //删除第i个表项,通过x返回表项的值
    bool IsEmpty()
    {
        return(last == -1) ? true : false;  //判断表项是否为空
    }
    bool IsFull()
    {
        return(last == maxSize - 1) ? true : false;//判断表满
    }
    void input();                           //输入建立顺序表
    void output();                          //输出
    SeqList<T>operator=(SeqList<T> & L);        //表整体赋值
};

//构造函数和复制构造函数
template<class T>
SeqList<T>::SeqList(int sz)
{
    if (sz > 0)
    {
        maxSize = sz;
        last = -1;
        data = new T[maxSize];              //顺序表动态存储数组
        if (data == NULL)
        {
            cerr << "存储分配失败!" << endl;
            exit(1);
        }
    }
}

template<class T>
SeqList<T>::SeqList(SeqList<T> & L)         //复制构造函数创建L
{
    maxSize = L.Size();
    last = L.Length() - 1;
    T value;
    data = new T[maxSize];                  //顺序表动态存储数组
    if (data = NULL)
    {
        cerr << "内存分配错误" << endl;
        exit(1);
    }
    for (int i = 1; i <= last; i++)         //i是逻辑位置
    {
        L.getData(i, value);
        data[i - 1] = value;
    }
}

template<class T>
void SeqList<T>::reSize(int newSize)        //改变数组大小,扩大存储容量
{
    if (newSize == 0)
    {
        cerr << "无效的数组大小" << endl;
        return;
    }
    if (newSize != maxSize)                 //修改
    {
        T* newarray = new T[newSize];       //新建数组
        if (newarray == NULL)
        {
            cerr << "存储分配错误" << endl;
            exit(1);
        }
        int n = last + 1;
        T* srcptr = data;               //源数组首地址
        T* destptr = newarray;          //目的数组首地址
        while (n--)
        {
            *destptr++ = *srcptr++;     //复制
        }
        delete[]data;                   //删除老数组
        data = newarray;                //data指向新数组
        maxSize = newSize;              //改变masSize
    }
}

template<class T>
int SeqList<T>::Search(T & x)const      //搜索
{
    for (int i = 0; i <= last; i++)
    {
        if (x == data[i])
            return i + 1;
    }
    return -1;
}

template<class T>
int SeqList<T>::Locate(int i)const      //定位
{
    if (i < last + 1 && i >= 0)
        return i - 1;
    return -1;
}

template<class T>
bool SeqList<T>::Insert(int i, T & x)   //插入操作,插入数字作为第i个
{
    if (last == maxSize - 1)
        return false;
    if (i <= 0 || i >= maxSize)
        return false;
    for (int j = last; j >= i; j--)
        data[j + 1] = data[j];
    data[i] = x;
    last++;                             //这个很重要!!!
    return true;
}

template<class T>
bool SeqList<T>::Remove(int i, T & x)   //删除
{
    if (last == -1)
        return false;
    if (i >= last + 1 || i < 1)
        return false;
    x = data[i - 1];
    for (int j = i - 1; j < last; j++)
        data[j] = data[j + 1];
    data[last] = NULL;
    last--;
    return true;
}

template<class T>
void SeqList<T>::input()                //输入建立顺序表
{
    cout << "开始建立顺序表,请输入表中元素个数(不超过" << maxSize << "个)" << endl;
    while (1)
    {
        cin >> last;
        if (i >= maxSize)
            break;
        cout << "错误,输入元素个数最大为" << maxSize << "。" << endl;
    }
    for (int i = 0; i <= last; i++)
    {
        cout << "请输入第" << i + 1 << "个数:";
        cin >> data[i];
    }
}


template<class T>
void SeqList<T>::output()           //将整个表输出
{
    cout << "现在输出整个表,表中总共有" << last + 1 << "项元素,下面是各项元素:" << endl;
    for (int i = 0; i <= last; i++)
        cout << "#" << i + 1 << ":" << data[i] << endl;
}

template<class T>
SeqList<T> SeqList<T>::operator=(SeqList<T> & L)
{
    maxSize = L.Size();
    last = L.Length() - 1;
    T value;
    data = new T[maxSize];                  //顺序表动态存储数组
    if (data = NULL)
    {
        cerr << "内存分配错误" << endl;
        exit(1);
    }
    for (int i = 1; i <= last; i++)         //i是逻辑位置
    {
        L.getData(i, value);
        data[i - 1] = value;
    }
}

单链表

头指针:指向第一个结点的地址
尾标志:终端结点的指针域为空
空表:first=NULL
头结点:在单链表的第一个元素结点之前附设一个类型相同的结点,以便在表的不同位置,或空表和非空表处理统一。
存储特点:
(1)逻辑次序和物理次序不一定相同。
(2)元素之间的逻辑关系用指针表示。
顺序表和链表的比较:
空间性能是指某种存储结构所占用的存储空间的大小。
时间性能是指实现基于某种存储结构的基本操作(即算法)的时间复杂度。

//对链表的操作都是通过指针来的
#include<iostream>
#include"linearList.h"
#include<stdlib.h>
using namespace std;
template <class T>
struct LinkNode             //结点类型定义
{
    T data;                 //结点数据域
    LinkNode<T>* Link;          //链指针域
    LinkNode(LinkNode<T>* ptr = NULL) { Link = ptr; }//初始化成员指针的构造函数
    LinkNode(const T& item, LinkNode<T>* ptr = NULL)
    {
        data = item;
        link = ptr;
    }
};

template<class T>
class List :public LinearList<T>
{
protected:
    LinkNode<T>* first;
public:
    List() { first = new LinkNode<T>; }         //构造函数
    List(const T& x) { first = new LinkNode<T>(x); }//构造函数
    List(List<T>& L);                               //复制构造函数
    ~List() { makeEmpty(); }                        // 析构函数
    void makeEmpty();                               // 制表为空表
    int Length()const;      //计算表长
    LinkNode<T>* getHead()const { return first; }   //返回头结点地址
    LinkNode<T>* Search(T x);       //搜索存有x的结点的地址
    LinkNode<T>* Locate(int i); //定位第i个结点的地址
    bool getData(int i, T& x)const; //返回第i个结点中的值
    void setData(int i, T& x);      //修改第i个结点中的值
    bool Insert(int i, T& x);       //在第i个元素后插入x
    bool Remove(int i, T& x);       //删除元素
    bool IsEmpty()const     //判断表空
    {
        return first->Link == NULL ? true : false;
    }
    bool IsFull()const { return false; }    //判断表满
    void Sort();    //排序
    void input();   //输出
    void output();  //输入
    List<T>& operator=(List<T>& L);    //重载复制函数
};

template<class T>
List<T>::List(List<T>& L)               //复制构造函数
{
    T value;
    LinkNode<T>* scrptr = L.getHead();  //从头节点开始
    LinkNode<T>* destptr = first = new LinkNode<T>;     //初始化一个头结点
    while (scrptr->Link != NULL)
    {
        value = scrptr->Link->data;
        destprt->Link = new LinkNode<T>(value);
        destptr = destptr->Link;
        scrptr = scrptr->Link;
    }
    destptr->Link = NULL;       //末尾结点处理
}

template<class T>
void List<T>::makeEmpty()       // 制表为空表
{
    LinkNode<T>* q;
    while (first->Link != NULL)     //当表不为空
    {
        q = first->Link;
        first->Link = first->Link->Link;
        delete q;       //一个一个删
    }
}

template<class T>
int List<T>::Length()const      //计算表长
{
    LinkNode* q = first->Link;
    int count = 0;
    while (p != NULL)       //一个一个找直到表尾
    {
        p = p->Link;
        count++;
    }
    return count;
}

template<class T>
LinkNode<T>* List<T>::Search(T x)       //返回存有某个元素的结点的下标
{
    LinkNode* q = first->Link;
    while (q != NULL)
    {
        if (q->data == x)
            return q;
        q = q->Link;
    }
    if (q == NULL)
        return NULL;
}

template<class T>
LinkNode<T>* List<T>::Locate(int i)     //定位第i个结点的地址
{
    if (i < 0)
        return NULL;
    LinkNode* current = first;
    int k = 0;
    while (current != NULL && k < i)
    {
        current = current->Link;
        k++;
    }
    if (current == NULL)
        return NULL;
    else
        return current;
}

template<class T>
bool List<T>::getData(int i, T & x)const        //返回第i个结点的元素
{
    if (i < = 0)
        return NULL;
    LinkNode<T> * current = Locate(i);
    if (current == NULL)
        return false;
    else
    {
        x = current->data;
        return true;
    }
}

template<class T>
void List<T>::setData(int i, T & x)     //重置第i个结点
{
    if (i <= 0)
        return;
    LinkNode * current = Locate(i);
    if (current == NULL)
        return;
    else
        current->data = x;
}

template<class T>
bool List<T>::Insert(int i, T & x)      //在第i个元素后插入x
{
    if (i <= 0)
        return false;
    LinkNode * current = Locate(i);
    LinkNode * p = new LinkNode<T>(x);
    if (p == NULL)
    {
        cerr << "内存分配失败" << endl;
        return false;
    }
    if (current == NULL)
        return false;
    p->Link = current->Link;
    current->Link = p;
    return true;
}

template<class T>
bool List<T>::Remove(int i, T & x)      //删除第i个元素
{
    LinkNode* current = Locate(i - 1);
    LinkNode * p = current->Link;
    if (i <= 1)
        return false;
    if (p == NULL || current == NULL)
        return false;
    current->Link = p->Link;
    x = p->data;
    delete p;
    return true;
}

template<class T>
void List<T>::output()
{
    LinkNode<T>* current = first->Link;
    while (current != NULL)
    {
        cout << current->data << endl;
        current = current - Link;
    }
}

template<class T>
void List<T>::input()
{
    cout << "开始建立单链表,请输入需要记录的数据个数" << endl;
    int x, num = 0;
    cin >> x;
    if (x <= 0)return;
    cout << "请依次输入需要记录的数据:" << endl;
    LinkNode<T> * p = first;
    T k;
    while (1)
    {
        cin >> k;
        LinkNode<T>* q = new LinkNode<T>(k);
        p->Link = q;
        p = p->Link;
        num++;
        if (num == x)
            break;
    }
    q->Link = NULL;
}

template<class T>
List<T>& List<T>::operator=(List<T> & L)
{
    T value;
    LinkNode<T>* scrptr = L.getHead();  //从头节点开始
    LinkNode<T>* destptr = first = new LinkNode<T>;     //初始化一个头结点
    while (scrptr->Link != NULL)
    {
        value = scrptr->Link->data;
        destprt->Link = new LinkNode<T>(value);
        destptr = destptr->Link;
        scrptr = scrptr->Link;
    }
    destptr->Link = NULL;       //末尾结点处理
}

template<class T>
void List<T>::Sort()
{
    LinkNode<T>* scrptr, change, p;
    scrptr = first->Link;
    T q;
    for (; scrptr->Link != NULL; scrptr = scrptr->Link)
    {
        change = scrptr;
        for (p = change->Link; p != NULL; p = p->Link)
        {
            if (change->data > p->data)
                change = p;
        }
        if (change != scrptr)
        {
            q = scrptr->data;
            scrptr->data = change->data;
            change->data = q;
        }
    }
    return;
}

问题 C: 火车出站
题目描述
铁路进行列车调度时,常把站台设计成栈式结构的站台,试问:
设有编号为1到n的n辆列车,顺序开入栈式结构的站台,则可能的出栈序列有多少种?
输入
输入包含多组测试数据。每组为一个正整数n(1<=n<=20),表示有n辆列车。
输出
输出可能的出栈序列有多少种。
样例输入
4
3
样例输出
14
5

//#define debug
#define undebug
#include <iostream>
#include<vector>
using namespace std;

void fuction(int n)
{
    vector<long long> array;
    array.push_back (1);
    array.push_back(1);
    long long b, c;
    if(n>1)
    {
        for(long long i=2;i<n+1;i++)
        {
            long long a = 0;
            for(long long j=0;j<i;j++)
            {
                b = array[j];
                c= array[i - j-1];
                a+=b*c;
            }
            array.push_back(a);
        }
    }
    cout<< array[n]<<endl;
    return;
}

int main()
{
    int n;
#ifdef debug
    for(int i=1;i<=20;i++)
        fuction(i);
    return 0;
#endif
#ifdef undebug
    while(cin>>n)
        fuction(n);
    return 0;
#endif
}

栈的类建立:

// 顺序栈.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include<assert.h>
#include"stack.h"
const int stackIncreasement = 20;       //溢出时的空间增量
template<class T>
class SeqStack:public Stack<T>
{
private:
    T* elements;
    int top;
    int maxSize;
    void overflowProcess();
public:
    SeqStack(int sz = 50);      //建立一个空栈
    ~SeqStack()
    {
        delete[]elements;
    }
    void Push(const T& x);      //把x插入到栈顶(如果栈没有满)
    bool Pop(T& X);     //退掉栈顶元素
    bool getTop(T& x);      //获取栈顶元素值
    bool IsEmpty()const { return(top == -1) ? true : false; }       //判断栈空
    bool IsFull()const { return (top = maxSize - 1) ? true : false; }       //判断栈是否满
    int getSize()const { return top + 1; }      //返回栈中元素个数
    void MakeEmpty() { top = -1; }
    friend ostream& operator<<(ostream& os, SeqStack<T>& s);        //输出
};

template<class T>
SeqStack<T>::SeqStack(int sz) :top(-1), maxSize(sz)
{
    elements = new T[maxSize];
    assert(elements != NULL);
}

template<class T>
void SeqStack<T>::overflowProcess()     //溢出处理
{
    T* newArray = new T[maxSize + stackIncreasement];
    if (newArray == NULL)
    {
        cerr << "内存分配失败" << endl;
        exit(1);
    }
    for (int i = 0; i <= top; i++)
        newArray[i] = elements[i];
    maxSize += stackIncreasement;
    delete[]elements;
    elements = newArray;
}

template<class T>
void SeqStack<T>::Push(const T& x)      //x进栈
{
    if (IsFull)
        overflowProcess();
    elements{ ++top } = x;
}

template<class T>
bool SeqStack<T>::Pop(T& x)     //top出栈
{
    if (IsEmpty)
        return false;
    x = elements[top--];
    return true;
}

template<class T>
bool SeqStack<T>::getTop(T& X)      //取top的值
{
    if (IsEmpty)
        return false;
    x = top;
    return true;
}

template<class T>
ostream& operator<<(ostream& os, SeqStack<T>& s)        //输出
{
    os << "top=" << s.top << endl;
    for (int i = 0; i <= s.top; i++)
    {
        os << i << ":" << s.elements << endl;
    }
    return os;
}

二叉树

二叉树问题
题目描述
现给定一棵二叉树的先序遍历序列和中序遍历序列,要求你计算该二叉树的高度。
输入
输入包含多组测试数据,每组输入首先给出正整数N(<=50),为树中结点总数。下面2行先后给出先序和中序遍历序列,均是长度为N的不包含重复英文字母(区别大小写)的字符串。
输出
对于每组输入,输出一个整数,即该二叉树的高度。
样例输入
9
ABDFGHIEC
FDHGIBEAC
7
Abcdefg
gfedcbA
样例输出
5
7

#include<iostream>
#include<algorithm>
using namespace std;

int find(char* pre, char* mid, int n)   //用先序序列和中序序列求二叉树的高度
{
    if (n == 0)    //若没有结点,为空树
    {
        return 0;       //搜索到底了就返回长度
    }
    int i = 0;
    for(;i<n;i++)       //这个n???????
    {
        if (mid[i] == pre[0])  //找到根结点在中序的位置
            break;      //跳出循环时,i的值为结点下标加1,即为元素个数
    }
    int left = find(pre + 1, mid, i);  //左子树的深度,根节点左边就是左子树的元素个数
    int right = find(pre + i + 1, mid + i + 1, n - i - 1);   //右子树的深度,根节点的右边就是右子树元素的个数
    return max(left, right) + 1;  //返回左右子树深度中的较大值+根结点
}
int main()
{
    int n;
    while (cin >> n)
    {
        char* pre = new char[n + 1];
        char* mid = new char[n + 1];
        /*先序和中序,字符数组要多开辟一个存储单元放\0*/
        cin >> pre;
        cin >> mid;
        cout << find(pre, mid, n) << endl;
    }
    return 0;
}

非递归前序遍历

void BinaryTree::PreOrder(BinNode *root)
{
    stack<BinaryTree>astack;
    BinNode *pointer=root;
    astack.push(NULL);      //设置监哨
    while(pointer)
    {
        visit(pointer->value);
        if(pointer->rightchild!=NULL);
            astack.push(pointer->leftchild);
        if(pointer->leftchild!=NULL)
            pointer=pointer->leftchild;     //左路下降
        else
        {
            pointer=astack.top();
            astack.pop();
        }       
    }
}

二叉排序树
题目描述
输入一系列整数,建立二叉排序数,并进行前序,中序,后序遍历。
输入
输入第一行包括一个整数n(1<=n<=100)。接下来的一行包括n个整数。
输出
可能有多组测试数据,对于每组数据,将题目所给数据建立一个二叉排序树,
并对二叉排序树进行前序、中序和后序遍历。每种遍历结果输出一行。每行最后一个数据之后有一个空格。
样例输入
1
2
2
8 15
4
21 10 5 39
样例输出
2
2
2
8 15
8 15
15 8
21 10 5 39
5 10 21 39
5 10 39 21



#include<iostream>
using namespace std;

struct BinTreeNode
{
    int data;
    BinTreeNode* leftchild, * rightchild;
    BinTreeNode(int num=0)
    {
        data = num;
        leftchild = NULL;
        rightchild = NULL;
    }
};

void set(int x, BinTreeNode* current )
{
    current->data = x;
}

void makeBinTree(int n,BinTreeNode *bin)        //建立二叉树
{
    int num;
    cin>>num;
    set(num,bin);
    BinTreeNode *p=new BinTreeNode;
    p = bin;
    for(int i=1;i<n;i++)
        {
            cin>>num;
            p=bin;
            while (p != NULL)
            {
                if (p->data == num)
                    break;
                if (p->data > num)
                {
                    if (p->leftchild == NULL)
                    {
                        p->leftchild = new BinTreeNode(num);
                        break;
                    }
                    p = p->leftchild;
                }
                else
                {
                    if (p->rightchild== NULL)
                    {
                        p->rightchild = new BinTreeNode(num);
                        break;
                    }
                    p = p->rightchild;
                }
            }
        }
}

void preOrder(BinTreeNode *bin)     //先序遍历
{
    if(bin!=NULL)
    {
        cout<<bin->data<<" ";
        preOrder(bin->leftchild);
        preOrder(bin->rightchild);
    }
}

void inorder(BinTreeNode *bin)      //中序遍历
{
    if(bin!=NULL)
    {
        inorder(bin->leftchild);
        cout<<bin->data<<" ";
        inorder(bin->rightchild);
    }
}

void postorder(BinTreeNode *bin)        //后序遍历
{
    if(bin!=NULL)
    {
        postorder(bin->leftchild);
        postorder(bin->rightchild);
        cout<<bin->data<<" ";
    }
}

int main()
{
    int n;
    while(cin>>n)
    {
        BinTreeNode *bin=new BinTreeNode;
        makeBinTree(n,bin);
        preOrder(bin);
        cout << endl;
        inorder(bin);
        cout << endl;
        postorder(bin);
        cout << endl;
    }
}

二叉排序树删除结点

//改进的二叉搜索树结点删除
void BinSearchTree::delete(BinNode *pointer)
{
    if(pointer==NULL)
        return;
    BinNode *temppointer;       //替换结点
    BinNode *tempparent;        //替换结点的父节点
    BinNode *parent=Parent(pointer);    //待删除结点的父节点
    if(pointer->leftchild==NULL)        //待删除结点无左节点时
        temppointer=pointer->rightchild;
    else
    {
        temppointer=pointer->leftchild;
        while(temppointer->rightchild!=NULL)
        {
            tempparent=temppointer;
            temppointer=temppointer->rightchild;        //向右下降找最大值
        }
        if(temppointer==NULL)
            pointer->leftchild=temppointer;     //如果被删结点左子树第一个结点没有右孩子
        else 
            tempparent->rightchild=temppointer->leftchild;
        temppointer->leftchild=pointer->leftchild;
        temppointer->rightchild=pointer->rightchild;
    }
    if(parent==NULL)
        root=temppointer;
    else if(parent->leftchild==pointer)
        parent->leftchild=temppointer;
    else 
        parent->rightchild=temppointer;
    pointer=NULL;
    delete pointer;
    return;
}

哈夫曼树

问题 B: 哈夫曼树
题目描述
哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,
根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。
输入
输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。
输出
输出权值。
样例输入
2
2 8
3
5 11 30
样例输出
10
62

#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int main()
{
    int n,num,a,b;
    while(cin>>n)
    {
        priority_queue<int,vector<int>,greater<int>>A;
        for(int i=0;i<n;i++)
        {
            cin>>num;
            A.push(num);
        }
        int total=0;
        while(A.size()!=1)      //最后一个不用再加了
        {
            a=A.top();
            A.pop();
            b=A.top();
            A.pop();
            total=total+a+b;
            A.push(a+b);
        }
        cout<<total<<endl;
    }
    return 0;
}

递归

题目描述
小明置身于一个迷宫,请你帮小明找出从起点到终点的最短路程。
小明只能向上下左右四个方向移动。
输入
输入包含多组测试数据。输入的第一行是一个整数T,表示有T组测试数据。
每组输入的第一行是两个整数N和M(1<=N,M<=100)。
接下来N行,每行输入M个字符,每个字符表示迷宫中的一个小方格。
字符的含义如下:
‘S’:起点
\‘E’:终点
‘-’:空地,可以通过
‘#’:障碍,无法通过
输入数据保证有且仅有一个起点和终点。
输出
对于每组输入,输出从起点到终点的最短路程,如果不存在从起点到终点的路,则输出-1。
样例输入
1
5 5
S-###
-----
##---
E#---
---##
样例输出
9

DFS:

#include <iostream>     //注意,这个程序是n行m列,和我们平常的nm的含义不一样
#include<vector>
#include<queue>
using namespace std;
priority_queue<int, vector<int>, greater<int> > q;      //存路径
void visit( vector< vector<int> > cell,int i,int j,int endi,int endj,int n,int m)       //找路径
{
    if(i==endi&&j==endj)
    {
        int all=0;
        for(int nn=0;nn<n;nn++)
            for(int mm=0;mm<m;mm++)
                if(cell[nn][mm]==1)
                    all++;
        q.push(all);
    
    }
    cell[i][j]=1;       //走过的设为1

    if(j-1>=0&&cell[i][j-1]==0)
        visit(cell,i,j-1,endi,endj,n,m);

    if(j+1<m&&cell[i][j+1]==0)
        visit(cell,i,j+1,endi,endj,n,m);

    if(i-1>=0&&cell[i-1][j]==0)
        visit(cell,i-1,j,endi,endj,n,m);

    if(i+1<n&&cell[i+1][j]==0)
        visit(cell,i+1,j,endi,endj,n,m);

    cell[i][j]=0;       //都不行就设置成0
}

int main()
{
    int times;
    cin>>times;     //表示有times组测试数据
    int m,n;
    int starti=0,startj=0,endi=0,endj=0;        //起点和终点
    char current;
    for(int i=0;i<times;i++)
    {
        cin>>n;     //n行
        cin>>m;     //m列
        vector< vector<int> > cell(n, vector<int>(m));
        for(int nn=0;nn<n;nn++)     //录入迷宫
            for(int mm=0;mm<m;mm++)
            {
                cin>>current;
                if(current=='S')
                {
                    starti=nn;
                    startj=mm;
                    cell[nn][mm]=0; 
                }
                if(current=='E')
                {
                    endi=nn;
                    endj=mm;
                    cell[nn][mm]=0;                         
                }
                if(current=='-')
                    cell[nn][mm]=0;     //表示可以走
                if(current=='#')
                    cell[nn][mm]=2;     //表示围墙
            }
        visit(cell,starti,startj,endi,endj,n,m);
        if(q.size()==0)
            cout<<-1;
        if(q.size()!=0)
            cout<<q.top();
        while(!q.empty())
            q.pop();
    }
    return 0;
}

BFS:

#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int starti , startj , endi , endj ;     //起点和终点
struct Position     //记录四个移动方向
{
    int row;
    int col;
    Position(int x,int y):row(x),col(y){}
};

 vector< vector<int> >Input(int n,int m)
{
        vector< vector<int> > cell(n + 2, vector<int>(m + 2));     //n+2行,m+2列
        char current;
        for (int nn = 0; nn < n + 2; nn++)      //录入迷宫
            for (int mm = 0; mm < m + 2; mm++)
            {
                if (nn == 0 || mm == 0 || nn == n + 1 || mm == m + 1)
                {
                    cell[nn][mm] = 2;     //最外面一圈用2围起来
                    continue;
                }
                cin >> current;        //把迷宫转化为数字矩阵
                if (current == 'S')
                {
                    starti = nn;
                    startj = mm;
                    cell[nn][mm] = 2;       //初始的位置不能再走了
                }
                if (current == 'E')
                {
                    endi = nn;
                    endj = mm;
                    cell[nn][mm] = 0;
                }
                if (current == '-')
                    cell[nn][mm] = 0;       //表示可以走
                if (current == '#')
                    cell[nn][mm] = 2;       //表示围墙
            }
        return cell;
}

/*寻找路径,若找到返回长度,没有路径返回-1*/
int FindPath(vector< vector<int> > cell)    
{
    Position offsets[4] = { {0,1},{1,0},{0,-1},{-1,0} };
    Position here(starti,startj),nbr(0,0);
    queue<Position>Q;
    while(1)
    {
        for(int i=0;i<4;i++)
        {
            nbr.row=here.row+offsets[i].row;
            nbr.col=here.col+offsets[i].col;
            if (cell[nbr.row][nbr.col] == 0)
            {
                cell[nbr.row][nbr.col] = cell[here.row][here.col] + 1;
                Q.push(nbr);        //能走才存,不能走不存
            }
            if(nbr.row==endi&&nbr.col==endj)
                break;      
        }
        if(nbr.row==endi&&nbr.col==endj)
            break;
        if(Q.empty())
            return -1;
        here=Q.front();
        Q.pop();
    }
    return cell[nbr.row][nbr.col]-2;    //最开始把起点步数设成2 了
}   

int main()
{
    int times;
    cin >> times;       //表示有times组测试数据
    int m, n;
    for (int i = 0; i < times; i++)
    {
        cin >> n;       //n行
        cin >> m;       //m列    
        vector< vector<int> > cell=Input(n, m);
        cout<<FindPath(cell)<<endl;
    }
    return 0;
}

汉诺塔

//求解n阶汉诺塔
#include<iostream>
#include<string.h>
using namespace std;

void Hanoi(int n,string A,string B,string C)
{
    if(n==1)
        cout<<"Move top desk from peg"<<A<<"to peg"<<C<<endl;
    else
    {
        Hanoi(n-1,A,C,B);
        cout<<"Move top desk from peg"<<A<<"to peg"<<C<<endl;
        Hanoi(n-1,B,A,C);
    }
}

int main()
{
    int n;
    cin>>n;
    Hanoi(n,'A','B','C');
    return 0;
}

Hanoi双塔问题

题目描述
给定A,B,C三根足够长的细柱,在A柱上放有2n个中间有空的圆盘,共有n个不同的尺寸,每个尺寸都有两个相同的圆盘,注意这两个圆盘是不加区分的(下图为n=3的情形)。现要将 这些国盘移到C柱上,在移动过程中可放在B柱上暂存。要求:
(1)每次只能移动一个圆盘;
(2) A、B、C三根细柱上的圆盘都要保持上小下大的顺序;
任务:设An为2n个圆盘完成上述任务所需的最少移动次数,对于输入的n,输出An。
输入
输入文件hanoi.in为一个正整数n,表示在A柱上放有2n个圆盘。
输出
输出文件hanoi.out仅一行,包含一个正整数,为完成上述任务所需的最少移动次数An。
样例输入
1
样例输出
2
提示
对于50%的数据, 1<=n<=25
对于100% 数据, 1<=n<=200
设法建立An与An-1的递推关系式。

#include <iostream>
#include<cmath>
#include <sstream>
using namespace std;

int main()
{
    stringstream sstream;
    long long n;
    cin >> n;
    sstream.precision(0);
    sstream << fixed << pow(2.0L, n + 1);  
    string a = sstream.str();    
    a[a.length() - 1]--;
    a[a.length() - 1]--;   
    cout << a << endl;
    return 0;
}

排序

快速排序
输入
输入的第一行包含1个正整数n,表示共有n个整数需要参与排序。其中n不超过100000。
第二行包含n个用空格隔开的正整数,表示n个需要排序的整数。
输出
只有1行,包含n个整数,表示从小到大排序完毕的所有整数。
请在每个整数后输出一个空格,并请注意行尾输出换行。
样例输入
10
2 8 4 6 1 10 7 3 5 9
样例输出
1 2 3 4 5 6 7 8 9 10

#include <iostream>
#include<algorithm>
using namespace std;

int division(int *list, int left, int right) 
{
    // 以最左边的数(left)为基准
    int base = list[left];
    while (left < right) {
        // 从序列右端开始,向左遍历,直到找到小于base的数
        while (left < right && list[right] >= base)
            right--;
        // 找到了比base小的元素,将这个元素放到最左边的位置
        list[left] = list[right];

        // 从序列左端开始,向右遍历,直到找到大于base的数
        while (left < right && list[left] <= base)
            left++;
        // 找到了比base大的元素,将这个元素放到最右边的位置
        list[right] = list[left];
    }

    // 最后将base放到left位置。此时,left位置的左侧数值应该都比left小;
    // 而left位置的右侧数值应该都比left大。
    list[left] = base;
    return left;
}

void quickSort(int* list, int left, int right){

    // 左下标一定小于右下标,否则就越界了
    if (left < right) {
        // 对数组进行分割,取出下次分割的基准标号
        int base = division(list, left, right);

        // 对“基准标号“左侧的一组数值进行递归的切割,以至于将这些数值完整的排序
        quickSort(list, left, base - 1);

        // 对“基准标号“右侧的一组数值进行递归的切割,以至于将这些数值完整的排序
        quickSort(list, base + 1, right);
    }
}

int main()
{
    int n;
    cin>>n;
    int *A=new int[n];
    int a;
    for (int i = 0; i < n; i++)
    {
        cin >> a;
        A[i] = a;
    }
    quickSort(A,0,n-1);     //初始与末尾位置
    for(int i = 0; i < n; i++)
        cout << A[i] << " ";
    cout<<endl;
    return 0;
}


常规cpp

题目1168:
字符串的查找删除
题目描述:
给定一个短字符串(不含空格),再给定若干字符串,在这些字符串中删除所含有的短字符串。
输入:
输入只有1组数据。
输入一个短字符串(不含空格),再输入若干字符串直到文件结束为止。
输出:
删除输入的短字符串(不区分大小写)并去掉空格,输出。
样例输入:
in
#include
int main()
{

printf(" Hi ");
}
样例输出:
#clude
tma()
{

prtf("Hi")}
提示:
注:将字符串中的In、IN、iN、in删除。**/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
using namespace std;

int Equal(char a, char b) {
    //通过a和b的绝对值判断两个字母是否“相等”
    if (abs(a - b) == 32 || a == b) return 1;
    else return 0;
}

int main()
{
    char c[1000], b[1000];
    gets(c);
    while (gets(b) != NULL) {
        int len = strlen(b);
        for (int i = 0; i < len; i++) {
            //如果b字符串中有字符和c[0]相等的字符就开始匹配
            if (Equal(b[i], c[0])) {
                int j = 1;
                i++; //b的下标加1
                while (j < strlen(c) && Equal(b[i], c[j])) {
                    i++;
                    j++;
                }
                //表示匹配成功,将b中匹配到的部分置为空格
                if (j == strlen(c)) {
                    for (int k = i - j; k < i; k++) {
                        b[k] = ' ';
                    }
                }
                i--;
            }
        }
        //去除空格输出
        for (int i = 0; i < len; i++) {
            if (b[i] != ' ') {
                cout<<b[i];
            }
        }
        cout<<endl;
    }

    return 0;
}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269