常见数据结构c++模板

链表

单链表

/*************************************************
**************************************************/
#include<iostream> //引入输入输出流
using namespace std;
template <typename DataType>
struct Node
{
    DataType data; //数据域
    Node *next; //指针域
};

template <typename DataType>
class LinkList
{
public:
    LinkList( ); //无参构造函数,建立只有头结点的空链表
    LinkList(DataType a[ ], int n); //有参构造函数,建立有n个元素的单链表
    ~LinkList( ); //析构函数
    int Length( ); //求单链表的长度
    int Empety();
    DataType Get(int i); //按位查找。查找第i个结点的元素值
    int Locate(DataType x); //按值查找。查找值为x的元素序号
    void Insert(int i, DataType x); //插入操作,第i个位置插入值为x的结点
    DataType Delete(int i); //删除操作,删除第i个结点
    void PrintList( ); //遍历操作,按序号依次输出各元素
private:
    Node<DataType> *first; //单链表的头指针
};

template <typename DataType>
LinkList<DataType> :: LinkList( )
{
    first = new Node<DataType>; //生成头结点
    first->next = nullptr; //头结点的指针域置空
}

template <typename DataType>
LinkList<DataType> :: ~LinkList( )
{
    Node<DataType> *q = NULL;
    while (first != NULL) //释放单链表的每一个结点的存储空间
    {
        q = first; //暂存被释放结点
        first = first->next; // first指向被释放结点的下一个结点
        delete q;
    }
}

template <typename DataType>
int LinkList<DataType> :: Empety()
{
    if(first->next == nullptr)
        return 1;
    else
        return 0;
}

template <typename DataType>
void LinkList<DataType> :: PrintList( )
{
    Node<DataType> *p = first->next; //工作指针p初始化
    while (p != nullptr)
    {
        cout << p->data << " ";
        p = p->next; //工作指针p后移,注意不能写作p++
    }
}

template <typename DataType>
int LinkList<DataType> :: Length( )
{
    Node<DataType> *p = first->next; //工作指针p初始化为开始接点
    int count = 0; //累加器count初始化
    while (p != nullptr)
    {
        p = p->next;
        count++;
    }
    return count; //注意count的初始化和返回值之间的关系
}

template <typename DataType>
DataType LinkList<DataType> :: Get(int i)
{
    Node<DataType> *p = first->next; //工作指针p初始化
    int count = 1; //累加器count初始化
    while (p != nullptr && count < i)
    {
        p = p->next; //工作指针p后移
        count++;
    }
    if (p == nullptr) throw "位置";
    else return p->data;
}

template <typename DataType>
int LinkList<DataType> :: Locate(DataType x)
{
    Node<DataType> *p = first->next; //工作指针p初始化
    int count = 1; //累加器count初始化
    while (p != nullptr)
    {
        if (p->data == x) return count; //查找成功,结束函数并返回序号
        p = p->next;
        count++;
    }
    return 0; //退出循环表明查找失败
}

template <typename DataType>
void LinkList<DataType> :: Insert(int i, DataType x)
{
    Node<DataType> *p = first, *s = nullptr ; //工作指针p初始化
    int count = 0;
    while (p != nullptr && count < i - 1) //查找第i – 1个结点
    {
        p = p->next; //工作指针p后移
        count++;
    }
    if (p == nullptr) throw "位置"; //没有找到第i – 1个结点
    else
    {
        s = new Node<DataType>;
        s->data = x; //申请结点s,数据域为x
        s->next = p->next;
        p->next = s; //将结点s插入到结点p之后
    }
}

// 头插法构造
//template
//LinkList :: LinkList(DataType a[ ], int n)
//{
// first = new Node; first->next = nullptr; //初始化一个空链表
// for (int i = 0; i < n; i++)
// {
// Node *s;
// s = new Node; s->data = a[i];
// s->next = first->next; first->next = s; //将结点s插入到头结点之后
// }
//}

template <typename DataType>
LinkList<DataType> :: LinkList(DataType a[ ], int n)
{
    first = new Node<DataType>; //生成头结点
    Node<DataType> *r = first, *s = nullptr; //尾指针初始化
    for (int i = 0; i < n; i++)
    {
        s = new Node<DataType>;
        s->data = a[i];
        r->next = s;
        r = s; //将结点s插入到终端结点之后
    }
    r->next = nullptr; //单链表建立完毕,将终端结点的指针域置空
}

template <typename DataType>
DataType LinkList<DataType> :: Delete(int i)
{
    DataType x;
    Node<DataType> *p = first, *q = nullptr; //工作指针p指向头结点
    int count = 0;
    while (p != nullptr && count < i - 1) //查找第i-1个结点
    {
        p = p->next;
        count++;
    }
    if (p == nullptr || p->next == nullptr) //结点p不存在或p的后继结点不存在
        throw "位置";
    else
    {
        q = p->next;
        x = q->data; //暂存被删结点
        p->next = q->next; //摘链
        delete q;
        return x;
    }
}

int main( )
{
    int r[5] = {1, 2, 3, 4, 5}, i, x;
    LinkList<int> L{r, 5};
    cout << "当前线性表的数据为:";
    L.PrintList( ); //输出当前链表1 2 3 4 5
    cout << endl;
    try
    {
        L.Insert(2, 8); //在第2个位置插入值为8的结点
        cout << "执行插入操作后数据为:";
        L.PrintList( ); //输出插入后链表1 8 2 3 4 5
        cout << endl;
    }
    catch(char* str)
    {
        cout << str << endl;
    }

    cout << "当前单链表的长度为:" << L.Length( ) << endl; //输出单链表长度6
    cout << "请输入查找的元素值:";
    cin >> x;
    i = L.Locate(x);
    if (1 <= i) cout << "元素" << x << "的元素位置为:" << i << endl;
    else cout << "单链表中没有元素" << x << endl;
    try
    {
        cout << "请输入要删除第几个元素:";
        cin >> i;
        x = L.Delete(i); //删除第i个元素
        cout << "删除的元素值是" << x << "执行删除操作后数据为:";
        L.PrintList( ); //输出删除后链表
    }
    catch(char* str)
    {
        cout << str << endl;
    }
    return 0;
}

双链表

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;


template <typename one>
struct Node
{
    one data;
    Node* piot;
    Node* next;
};
template <typename one>
class Double_linked_list
{
public:
    Double_linked_list(one a[],int n);
    Double_linked_list();
    ~Double_linked_list();
    int Length( );
    int Empety();
    one Get(int i);
    int Locate(one x); //按值查找。查找值为x的元素序号
    void Insert(int i, one x); //插入操作,第i个位置插入值为x的结点
    one Delete(int i); //删除操作,删除第i个结点
    void PrintList( ); //遍历操作,按序号依次输出各元素
private:
    Node<one> *first,*tail; //单链表的头指针
};
template <typename one>
Double_linked_list<one> :: Double_linked_list( )
{
    first = new Node<one>; //生成头结点
    first->next = nullptr; //头结点的指针域置空
}

template <typename one>
Double_linked_list<one> :: ~Double_linked_list( )
{
    Node<one> *q = NULL;
    while (first != NULL) //释放单链表的每一个结点的存储空间
    {
        q = first; //暂存被释放结点
        first = first->next; // first指向被释放结点的下一个结点
        delete q;
    }
}

template <typename one>
int Double_linked_list<one> :: Empety()
{
    if(first->next == nullptr)
        return 1;
    else
        return 0;
}

template <typename one>
void Double_linked_list<one> :: PrintList( )
{
    Node<one> *p = first->next; //工作指针p初始化
    while (p != nullptr)
    {
        cout << p->data << " ";
        p = p->next; //工作指针p后移,注意不能写作p++
    }
}

template <typename one>
int Double_linked_list<one> :: Length( )
{
    Node<one> *p = first->next; //工作指针p初始化为开始接点
    int count = 0; //累加器count初始化
    while (p != nullptr)
    {
        p = p->next;
        count++;
    }
    return count; //注意count的初始化和返回值之间的关系
}

template <typename one>
one Double_linked_list<one> :: Get(int i)
{
    Node<one> *p = first->next; //工作指针p初始化
    int count = 1; //累加器count初始化
    while (p != nullptr && count < i)
    {
        p = p->next; //工作指针p后移
        count++;
    }
    if (p == nullptr)
        throw "位置";
    else
        return p->data;
}

template <typename one>
int Double_linked_list<one> :: Locate(one x)
{
    Node<one> *p = first->next; //工作指针p初始化
    int count = 1; //累加器count初始化
    while (p != nullptr)
    {
        if (p->data == x)
            return count; //查找成功,结束函数并返回序号
        p = p->next;
        count++;
    }
    return 0; //退出循环表明查找失败
}

template <typename one>
void Double_linked_list<one> :: Insert(int i, one x)
{
    Node<one> *p = first, *s = nullptr ; //工作指针p初始化
    int count = 0;
    while (p != nullptr && count < i - 1) //查找第i – 1个结点
    {
        p = p->next; //工作指针p后移
        count++;
    }
    if (p == nullptr)
        throw "位置"; //没有找到第i – 1个结点
    else
    {
        s = new Node<one>;
        s->data = x; //申请结点s,数据域为x
        s->next = p->next;
        s->piot = p;
        p->next->piot = s;
        p->next = s; //将结点s插入到结点p之后
    }
}
// 头插法构造
//template
//Double_linked_list :: Double_linked_list(one a[ ], int n)
//{
// first = new Node; first->next = nullptr; //初始化一个空链表
// for (int i = 0; i < n; i++)
// {
// Node *s;
// s = new Node; s->data = a[i];
// s->next = first->next; first->next = s; //将结点s插入到头结点之后
// }
//}
template <typename one>
Double_linked_list<one> :: Double_linked_list(one a[ ], int n)
{
    first = new Node<one>; //生成头结点
    tail = new Node<one>;
    tail->piot = nullptr;
    Node<one> *r = first, *s = nullptr; //尾指针初始化
    for (int i = 0; i < n; i++)
    {
        s = new Node<one>;
        s->data = a[i];
        s->piot = tail->piot;
        tail->piot = s;
        r->next = s;
        r = s; //将结点s插入到终端结点之后
    }
    r->next = nullptr; //单链表建立完毕,将终端结点的指针域置空
}

template <typename one>
one Double_linked_list<one> :: Delete(int i)
{
    one x;
    Node<one> *p = first, *q = nullptr; //工作指针p指向头结点
    int count = 0;
    while (p != nullptr && count < i - 1) //查找第i-1个结点
    {
        p = p->next;
        count++;
    }
    if (p == nullptr || p->next == nullptr) //结点p不存在或p的后继结点不存在
        throw "位置";
    else
    {
        q = p->next;
        x = q->data; //暂存被删结点
        p->next = q->next; //摘链
        q->next->piot = p;
        delete q;
        return x;
    }
}

int main( )
{
    int r[5] = {1, 2, 3, 4, 5}, i, x;
    Double_linked_list<int> L{r, 5};
    cout << "当前线性表的数据为:";
    L.PrintList( ); //输出当前链表1 2 3 4 5
    cout << endl;
    try
    {
        L.Insert(2, 8); //在第2个位置插入值为8的结点
        cout << "执行插入操作后数据为:";
        L.PrintList( ); //输出插入后链表1 8 2 3 4 5
        cout << endl;
    }
    catch(char* str)
    {
        cout << str << endl;
    }

    cout << "当前单链表的长度为:" << L.Length( ) << endl; //输出单链表长度6
    cout << "请输入查找的元素值:";
    cin >> x;
    i = L.Locate(x);
    if (1 <= i)
        cout << "元素" << x << "的元素位置为:" << i << endl;
    else
        cout << "单链表中没有元素" << x << endl;
    try
    {
        cout << "请输入要删除第几个元素:";
        cin >> i;
        x = L.Delete(i); //删除第i个元素
        cout << "删除的元素值是" << x << "执行删除操作后数据为:";
        L.PrintList( ); //输出删除后链表
    }
    catch(char* str)
    {
        cout << str << endl;
    }
    return 0;
}

顺序表

#include<bits/stdc++.h>
using namespace std;
const int MaxSize = 100; //100只是示例性的数据,根据实际问题具体定义

template <typename DataType>
class SeqList
{
public:
    SeqList( ); //无参构造函数,建立空的顺序表
    SeqList(DataType a[ ], int n); //有参构造函数,建立长度为n的顺序表
    ~SeqList( ); //析构函数
    int Length( ); //求线性表的长度
    int Empety();
    DataType Get(int i); //按位查找,查找第i个元素的值
    int Locate(DataType x ); //按值查找,查找值为x的元素序号
    void Insert(int i, DataType x); //插入操作,在第i个位置插入值为x的元素
    DataType Delete(int i); //删除操作,删除第i个元素
    void PrintList( ); //遍历操作,按序号依次输出各元素
private:
    DataType data[MaxSize]; //存放数据元素的数组
    int length; //线性表的长度
};

template <typename DataType>
SeqList<DataType>:: ~SeqList()
{

}

template <typename DataType>
SeqList<DataType>:: SeqList()
{
    length = 0;
}

template <typename DataType>
int SeqList<DataType>:: Empety()
{
    if(length == 0)
        return 1;
    else
        return 0;
}

template < typename DataType >
int SeqList<DataType>:: Length()
{
    return length;
}

template <typename DataType>
SeqList<DataType>::SeqList(DataType a[ ], int n)
{
    if (n > MaxSize)
        throw "参数非法";
    for (int i = 0; i < n; i++)
        data[i] = a[i];
    length = n;
}

template <typename DataType>
void SeqList<DataType>:: PrintList( )
{
    for (int i = 0; i < length; i++)
        cout << data[i]; //依次输出线性表的元素值
}

template <typename DataType>
int SeqList<DataType>::Locate(DataType x)
{
    for (int i = 0; i < length; i++)
        if (data[i] == x)
            return i+1; //返回其序号i+1
    return 0; //退出循环,说明查找失败
}

template <typename DataType>
DataType SeqList<DataType>:: Get(int i)
{
    if (i < 1 && i > length)
        throw "查找位置非法";
    else
        return data[i - 1];
}

template <typename DataType>
DataType SeqList<DataType>:: Delete(int i)
{
    if (length == 0)
        throw "下溢";
    if (i < 1 || i > length)
        throw "位置";
    int x = data[i - 1]; //取出位置i的元素
    for (int j = i; j < length; j++)
        data[j - 1] = data[j]; //此处j已经是元素所在的数组下标
    length--;
    return x;
}

template <typename DataType>
void SeqList<DataType>::Insert(int i, DataType x)
{
    if (length >= MaxSize)
        throw "上溢";
    if (i < 1 || i > length + 1)
        throw "位置";
    for (int j = length; j >= i; j--)
        data[j] = data[j - 1]; //第j个元素存在数组下标为j-1处
    data[i - 1] = x;
    length++;
}

int main( )
{
    int r[5] = {1, 2, 3, 4, 5}, i, x;
    SeqList<int>L{r, 5}; //建立具有5个元素的顺序表
    cout << "当前线性表的数据为:";
    L.PrintList( ); //输出当前线性表1 2 3 4 5
    try
    {
        L.Insert(2, 8); //在第2个位置插入值为8的元素
        cout << endl << "执行插入操作后数据为:";
        L.PrintList( ); //输出插入后的线性表1 8 2 3 4 5
        cout << endl;
    }
    catch(char* str)
    {
        cout << str << "插入操作错误!" << endl;
    }

    cout << "当前线性表的长度为:" << L.Length( ); //输出线性表的长度6
    cout << endl;
    cout << "请输入查找的元素值:";
    cin >> x;
    i = L.Locate(x);
    if (0 == i)
        cout << "查找失败" << endl;
    else
        cout << "元素" << x << "的位置为:" << i << endl;
    try
    {
        cout << "请输入查找第几个元素值:";
        cin >> i;
        cout << "第" << i << "个元素值是" << L.Get(i) << endl;
    }
    catch(char* str)
    {
        cout << "线性表中没有该元素" << endl;
    }
    try
    {
        cout << "请输入要删除第几个元素:";
        cin >> i;
        x = L.Delete(i); //删除第i个元素
        cout << "删除的元素是" << x <<",删除后数据为:";
        L.PrintList( ); //输出删除后的线性表
    }
    catch(char* str)
    {
        cout << "删除错误!" << endl;
    }

    return 0;
}

栈与队列

表达式求值

/*********************************
表达式求值
**********************************/
#include <iostream>
#include <string>
using namespace std;

class Expression
{
public:
    Expression(string str); //构造函数
    ~Expression( ); //析构函数
    int Compute( ); //计算表达式str的值
private:
    int Comp(char str1, char str2); //比较str1的str2优先级
    string str;
};

Expression :: Expression(string str) //接收键盘输入并加上定界符
{
    this->str = str + "#";
}

Expression :: ~Expression( )
{

}

int Expression :: Compute( )
{
    char OPND[100], OPTR[100]; //定义两个顺序栈
    OPTR[0] = '#'; //栈OPTR初始化为定界符
    int top1 = -1, top2 = 0; //初始化栈OPND和OPTR的栈顶指针
    int i, k, x, y, z, op;
    for (i = 0; str[i] != '\0'; ) //依次扫描每一个字符
    {
        if (str[i] >= 48 && str[i] <= 57) //数字0的ASCII码是48
            OPND[++top1] = str[i++] - 48; //将字符转换为数字压栈
        else
        {
            k = Comp(str[i], OPTR[top2]);
            if (k == 1) //str[i]的优先级高
                OPTR[++top2] = str[i++]; //将str[i]压入运算符栈
            else if (k == -1) //str[i]的优先级低
            {
                y = OPND[top1--]; //从运算对象栈出栈两个元素
                x = OPND[top1--];
                op = OPTR[top2--]; //从运算符栈出栈一个元素
                switch (op) // op为运算符,进行相应运算
                {
                case '+':
                    z = x + y;
                    break;
                case '-':
                    z = x - y;
                    break;
                case '*':
                    z = x * y;
                    break;
                case '/':
                    z = x / y;
                    break;
                default:
                    break;
                }
                OPND[++top1] = z; //运算结果入运算对象栈
            }
            else
            {
                //str[i]与运算符栈的栈顶元素优先级相同
                top2--; //匹配str[i],扫描下一个字符
                i++;
            }
        }
    }
    return OPND[top1]; //运算对象栈的栈顶元素即为运算结果
}

int Expression :: Comp(char str1, char str2)
{
    //比较str1和str2的优先级,1:str1高;0:相同;-1:str1低
    switch (str1)
    {
    case '+':
    case '-':
        if (str2 == '(' || str2 == '#')
            return 1;
        else
            return -1;
        break;
    case '*':
    case '/':
        if (str2 == '*' || str2 == '/')
            return -1;
        else
            return 1;
        break;
    case '(':
        return 1;
        break;
    case ')':
        if (str2 == '(')
            return 0;
        else
            return -1;
        break;
    case '#':
        if (str2 == '#')
            return 0;
        else
            return -1;
        break;
    default:
        break;
    }
}

int main( )
{
    string str;
    cout << "请输入一个表达式:" << endl;
    cin >> str;
    Expression E{str}; //定义对象变量E
    int result = E.Compute( ); //result保存计算结果
    cout << "表达式的值是:" << result << endl;
    return 0;
}

括号匹配问题

/**********************************
括号匹配问题
***********************************/
#include<iostream>
#include<string>
using namespace std;

class Matcher{
public:
Matcher(string str);
~Matcher(){ };
int match();
private:
string str;
};

Matcher :: Matcher(string str){
this->str = str;
}

int Matcher :: match()
{
string S; /*定义一个字符对象 */
int i, top = -1; /* top为字符对象S的尾指针 */
for (i = 0; str[i] != '\0'; i++) /* 依次对str对象的每个字符, str[i]进行处理 */
{
if (str[i] == ')') { /*当前扫描的字符是右括号*/
if (top > -1) top--; /*出栈前判断栈是否为空*/
else return -1;
}
else if (str[i] == '(') /*当前扫描的字符是左括号*/
S[++top] = str[i]; /*执行入栈操作*/
}
if (top == -1) return 0; /*栈空则括号正确匹配*/
else return 1;
}


int main( )
{
string str; /*定义尽可能大的字符数组以接收键盘的输入*/
int k; /*k接收调用函数Match的结果*/
cout << "请输入一个算术表达式:";
cin >> str; /*将表达式以字符串方式输入*/
Matcher m{str};
k = m.match( ); /*函数调用,实参为字符数组的首地址*/
if (k == 0)
cout << "正确匹配\n";
else if (k == 1)
cout << "多左括号\n";
else
cout << "多右括号\n";
return 0;
}

链队列

/************************************************
链队列类LinkQueue的使用范例
*************************************************/
#include<iostream>
using namespace std;

template<typename DataType>
struct Node
{
    DataType data; //数据域
    Node *next; //指针域
};

template<typename DataType>
class LinkQueue
{
public:
    LinkQueue( ); //构造函数,初始化一个空的链队列
    ~LinkQueue( ); //析构函数,释放链队列各结点的存储空间
    void EnQueue(DataType x); //入队操作,将元素x入队
    DataType DeQueue( ); //出队操作,将队头元素出队
    DataType GetQueue( ); //取链队列的队头元素
    int Empty( ); //判断链队列是否为空
private:
    Node<DataType> *front, *rear; //队头和队尾指针,分别指向头结点和终端结点
};

template<typename DataType>
LinkQueue<DataType>:: LinkQueue( )
{
    Node<DataType> *s = nullptr;
    s = new Node<DataType>;
    s->next = nullptr; //创建头结点s
    front = rear = s; //将队头指针和队尾指针都指向头结点s
}

template<typename DataType>
LinkQueue<DataType>:: ~LinkQueue()
{
    Node<DataType>*q = nullptr;
    while (front != nullptr) //释放单链表的每一个结点的存储空间
    {
        q = front; //暂存被释放结点
        front = front->next; // front指向被释放结点的下一个结点
        delete q;
    }
}

template<typename DataType>
void LinkQueue<DataType>:: EnQueue(DataType x)
{
    Node<DataType> *s = nullptr;
    s = new Node<DataType>; //申请结点s
    s->data = x;
    s->next = nullptr;
    rear->next = s;
    rear = s; //将结点s插入到队尾
}

template<typename DataType>
DataType LinkQueue<DataType>:: DeQueue( )
{
    DataType x;
    Node<DataType>*p = nullptr;
    if (rear == front) throw "下溢";
    p = front->next;
    x = p->data; //暂存队头元素
    front->next = p->next; //将队头元素所在结点摘链
    if (p->next == nullptr) rear = front; //判断出队前队列长度是否为1
    delete p;
    return x;
}

template<typename DataType>
DataType LinkQueue<DataType>:: GetQueue()
{
    if(front == rear)
        throw "下溢异常";
    else
        return front->next->data;
}

template<typename DataType>
int LinkQueue<DataType>:: Empty()
{
    if(front == rear)
        return 1;
    else
        return 0;
}

int main( )
{
    int x;
    LinkQueue<int>Q{ }; //定义对象变量Q
    cout << "对5和8执行入队操作,";
    Q.EnQueue(5);
    Q.EnQueue(8);
    cout << "当前队头元素为:" << Q.GetQueue( ) << endl; //输出队头元素5

    try
    {
        x = Q.DeQueue( );
        cout << "执行一次出队操作,出队元素是:" << x << endl; //输出出队元素5
    }
    catch(char* str)
    {
        cout << str << endl;
    }

    try
    {
        cout << "请输入入队元素:";
        cin >> x;
        Q.EnQueue(x);
    }
    catch(char* str)
    {
        cout << str << endl;
    }

    if (Q.Empty( ) == 1) cout << "队列为空" << endl;
    else cout << "队列非空" << endl; //队列有2个元素,输出队列非空
    return 0;
}

链栈

/************************************************
链栈类LinkStack的使用范例
*************************************************/
#include<iostream>
using namespace std;

template<typename DataType>
struct Node
{
    DataType data; //数据域
    Node *next; //指针域
};

template<typename DataType>
class LinkStack
{
public:
    LinkStack( ); //构造函数,初始化一个空链栈
    ~LinkStack( ); //析构函数,释放链栈各结点的存储空间
    void Push(DataType x); //入栈操作,将元素x入栈
    DataType Pop( ); //出栈操作,将栈顶元素出栈
    DataType GetTop( ); //取栈顶元素(并不删除)
    int Empty( ); //判空操作,判断链栈是否为空栈
private:
    Node<DataType> *top; //栈顶指针即链栈的头指针
};

template<typename DataType>
LinkStack<DataType> :: LinkStack()
{
    top = new Node<DataType>; //生成头结点
    top->next = nullptr; //头结点的指针域置空
}

template<typename DataType>
LinkStack<DataType> :: ~LinkStack()
{
    Node<DataType> *q = nullptr;
    while (top != nullptr) //释放链栈的每一个结点的存储空间
    {
        q = top; //暂存被释放结点
        top = top->next; // top指向被释放结点的下一个结点
        delete q;
    }
}

template<typename DataType>
DataType LinkStack<DataType> :: GetTop()
{
    if(top == nullptr)
        throw "下溢异常";
    else
        return top->data;
}


template<typename DataType>
void LinkStack<DataType> :: Push(DataType x)
{
    Node<DataType> *s = nullptr;
    s = new Node<DataType>;
    s->data = x; //申请结点s数据域为x
    s->next = top;
    top = s; //将结点s插在栈顶
}

template<typename DataType>
DataType LinkStack<DataType> :: Pop( )
{
    Node<DataType> *p = nullptr;
    DataType x;
    if (top == nullptr) throw "下溢";
    x = top->data;
    p = top; //暂存栈顶元素
    top = top->next; //将栈顶结点摘链
    delete p;
    return x;
}

template<typename DataType>
int LinkStack<DataType> :: Empty()
{
    if(top == nullptr)
        throw "下溢异常";
    else
        return 0;
}

int main( )
{
    int x;
    LinkStack<int> S{ }; //定义链栈变量S
    cout << "对15和10执行入栈操作,";
    S.Push(15);
    S.Push(10);
    cout << "当前栈顶元素为:" << S.GetTop( ) << endl; //输出栈顶元素10
    try
    {
        x = S.Pop( );
        cout << "执行一次出栈操作,删除元素:" << x << endl; //输出出栈元素10
    }
    catch(char* str)
    {
        cout << str << endl;
    }
    try
    {
        cout << "请输入待插入元素:";
        cin >> x;
        S.Push(x);
    }
    catch(char* str)
    {
        cout << str << endl;
    }
    if (S.Empty( ) == 1) cout << "栈为空" << endl;
    else cout << "栈非空" << endl; //栈有2个元素,输出栈非空
    return 0;
}

逆波兰式

#include<iostream>
using namespace std;
typedef long long ll;
const int N = 110;

int Ints(char str1, char str2)
{
    switch(str1)
    {
        case'+':case'-':if(str2 == '(' || str2 == '#') return 1;else return -1;break;
        case'*':case'/':if(str2 == '*' || str2 == '/') return -1;else return 1;break;
        case'(':return 1;break;
        case')':if(str2 == '(') return 0;else return  -1;break;
        case'#':if(str2 == '#') return 0;else return  -1;break;

    }
}


ll Cals(string str)
{
    char Num[N],Oper[N];
    int top1 = -1, top2 = 0;
    Oper[top2] = '#';
    int z;
    for(int i = 0; str[i];)
    {
        if(str[i] >= 48 && str[i] <= 58) Num[++top1] = str[i++] - 48;
        else
        {
            int k = Ints(str[i],Oper[top2]);
            if(k == 1) Oper[++top2] = str[i++];
            else if(k == -1)
            {
                int y = Num[top1--];
                int x = Num[top1--];
                char op = Oper[top2--];
                switch(op)
                {
                    case'+': z = x + y;break;
                    case'-': z = x - y;break;
                    case'*': z = x * y;break;
                    case'/': z = x / y;break;
                    default:break;
                }
                Num[++top1] = z;
            }
            else
            {
                top2--;
                i++;
            }
        }
    }
    return Num[top1];
}
int main()
{
    string str;
    cin >> str;
    str+='#';
    ll sum = Cals(str);

    cout << sum << endl;
    return 0;
}

顺序栈

/************************************************
顺序栈类SeqStack的使用范例
*************************************************/
#include<iostream>
using namespace std;
const int StackSize = 10; //10是示例性的数据,根据实际问题具体定义
template <typename DataType>
class SeqStack
{
public:
    SeqStack( ); //构造函数,初始化一个空栈
    ~SeqStack( ); //析构函数
    void Push( DataType x ); //入栈操作,将元素x入栈
    DataType Pop( ); //出栈操作,将栈顶元素弹出
    DataType GetTop( ); //取栈顶元素(并不删除)
    int Empty( ); //判断栈是否为空
private:
    DataType data[StackSize]; //存放栈元素的数组
    int top; //游标,栈顶指针,为栈顶元素在数组中的下标
};

template<typename DataType>
SeqStack<DataType>:: SeqStack()
{
    top = -1;
}

template<typename DataType>
SeqStack<DataType>:: ~SeqStack()
{

}

template<typename DataType>
int SeqStack<DataType>:: Empty()
{
    if(top == -1)
        return 1;
    else
        return 0;
}

template<typename DataType>
DataType SeqStack<DataType>:: GetTop( )
{
    if(top == -1)
        throw "下溢异常";
    else
        return data[top];
}

template<typename DataType>
void SeqStack<DataType>:: Push(DataType x)
{
    if (top == StackSize - 1) throw "上溢";
    data[++top] = x;
}

template<typename DataType>
DataType SeqStack<DataType>:: Pop( )
{
    DataType x;
    if (top == -1) throw "下溢";
    x = data[top--];
    return x;
}

int main( )
{
    int x;
    SeqStack<int> S{ }; //定义顺序栈变量S
    cout << "对15和10执行入栈操作,";
    S.Push(15);
    S.Push(10);
    cout << "当前栈顶元素为:" << S.GetTop( ) << endl; //输出栈顶元素10
    try
    {
        x = S.Pop( );
        cout << "执行一次出栈操作,删除元素" << x << endl; //输出出栈元素10
    }
    catch(char* str)
    {
        cout << str << endl;
    }
    try
    {
        cout << "请输入待入栈元素:";
        cin >> x;
        S.Push(x);
    }
    catch(char* str)
    {
        cout << str << endl;
    }
    if (S.Empty( ) == 1) cout << "栈为空" << endl;
    else cout << "栈非空" << endl; //栈有2个元素,输出栈非空
    return 0;
}

循环队列

/*************************************************
循环队列类CirQueue的使用范例
**************************************************/
#include<iostream>
using namespace std;
const int QueueSize = 100; //100是示例性数据,根据需要重新定义
template <typename DataType>
class CirQueue
{
public:
    CirQueue( ); //构造函数,初始化空队列
    ~ CirQueue( ); //析构函数
    void EnQueue(DataType x); //入队操作,将元素x入队
    DataType DeQueue( ); //出队操作,将队头元素出队
    DataType GetQueue( ); //取队头元素(并不删除)
    int Empty( ); //判断队列是否为空
private:
    DataType data[QueueSize]; //存放队列元素的数组
    int front, rear; //游标,队头和队尾指针
};
template<typename DataType>
CirQueue<DataType>:: CirQueue()
{
    rear = front = QueueSize - 1;
}
template<typename DataType>
CirQueue<DataType>:: ~CirQueue()
{

}
template<typename DataType>
void CirQueue<DataType>:: EnQueue(DataType x)
{
    if ((rear + 1) % QueueSize == front)
        throw "上溢";
    rear = (rear + 1) % QueueSize; //队尾指针在循环意义下加1
    data[rear] = x; //在队尾处插入元素
}

template<typename DataType>
DataType CirQueue<DataType>:: DeQueue( )
{
    if (rear == front) throw "下溢";
    front = (front + 1) % QueueSize; //队头指针在循环意义下加1
    return data[front]; //读取并返回出队前的队头元素
}

template<typename DataType>
DataType CirQueue<DataType>:: GetQueue( )
{
    if (rear == front) throw "下溢";
    return data[(front + 1) % QueueSize]; //注意不修改队头指针
}

template<typename DataType>
int CirQueue<DataType>:: Empty()
{
    if(front == rear)
        return 1;
    else
        return 0;
}

int main( )
{
    int x;
    CirQueue<int>Q{ }; //定义对象变量Q
    cout << "对5和8执行入队操作,";
    Q.EnQueue(5);
    Q.EnQueue(8);
    cout << "当前队头元素为:" << Q.GetQueue( ) << endl; //输出队头元素5

    try
    {
        x = Q.DeQueue( );
        cout << "执行一次出队操作,出队元素是:" << x << endl; //输出出队元素5
    }
    catch(char* str)
    {
        cout << str << endl;
    }

    try
    {
        cout <<"请输入入队元素:";
        cin >> x;
        Q.EnQueue(x);
    }
    catch(char* str)
    {
        cout << str << endl;
    }

    if (Q.Empty( ) == 1) cout << "队列为空" << endl;
    else cout << "队列非空" << endl; //队列有2个元素,输出队列非空
    return 0;
}

KMP

#include<iostream>
using namespace std;
const int N = 1e5 + 10, M = 1e6 + 10;
int n,m;
int ne[N];
char s[M],p[N];
int main()
{
    cin >> n >> p + 1 >> m >> s + 1;
    for(int i = 2, j = 0; i <= n; i ++ )
    {
        while(j&&p[i]!=p[j+1]) j = ne[j];
        if(p[i]==p[j+1])j ++;
        ne[i] = j;
    }
    for(int i = 1, j = 0; i <= m; i ++ )
    {
        while(j&&s[i]!=p[j+1]) j = ne[j];
        if(s[i]==p[j+1]) j ++ ;
        if(j == n)
        {
            cout << i - n << " ";
            j = ne[j];
        }
    }
    return 0;
}

八皇后问题

#include<bits/stdc++.h>
using namespace std;
const int N = 1010;
bool hen[N],up[N*2+1],down[N*2+1];
int K;
 int n;
int main()
{
    cin >> K;
    while(K--)
    {
       
        memset(hen,0,sizeof hen);
        memset(up,0,sizeof up);
        memset(down,0,sizeof down);
        cin >> n;
        int it = true;
     for(int y = 1 ; y <= n ; y ++ ) 
    {
        int x;
        cin >> x;
        if(hen[x]||up[x+y]||down[y-x+n]) it = false;
        hen[x]=up[x+y]=down[y-x+n]=true;
    }
        if(it) cout <<"YES"<<endl;
        else cout <<"NO"<<endl;
    }
    return 0;
}

发纸牌问题

/******************************
发纸牌
*******************************/
#include <iostream>
#include <ctime>//使用库函数time
#include <cstring>
using namespace std;

int sign[4][13] = {0}; //标志数组
string str1[4] = {"梅花","黑桃","红桃","方块"}; //全局变量存储花色和点数
string str2[13] = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};

class PlayCard
{
public:
    PlayCard( );
    ~PlayCard( );
    void SendCards(int n);
    void PrintCards( );
private:
    string card[13];
    int number;
};

PlayCard :: PlayCard( )
{
    number = 0;
}

void PlayCard :: SendCards(int n)
{
    int i, j, k;
    number = n;
    memset(sign, 0, n); //初始化标志数组,所有牌均未发出
    srand(time(nullptr)); //初始化随机种子为当前系统时间
    for (k = 0; k < n; ) //省略表达式3,发第k张牌
    {
        i = rand( ) % 4 ; //随机生成花色的下标
        j = rand( ) % 13; //随机生成点数的下标
        if (sign[i][j] == 1) //这张牌已发出
            continue; //跳过循环体余下语句,注意k的值不变
        else
        {
            card[k] =str1[i] + str2[j]; //连接str1和str2,并复制给card数组
            sign[i][j] = 1; //标识这张牌已发出
            k++; //准备发下一张牌
        }
    }
}

PlayCard :: ~PlayCard( )
{

}

void PlayCard::PrintCards( )
{
    for (int k = 0; k < number; k++)
        cout << card[k] << " "; //输出第k张牌
    cout << endl;
}

int main( )
{
    int n;
    PlayCard P{ }; //创建对象变量P
    cout << "请输入要发牌的张数:";
    cin >> n;
    P.SendCards(n); //发n张牌
    P.PrintCards( ); //打印发出的牌
    return 0;
}

十字链表

#include<stdio.h>
#include<stdlib.h>
typedef struct OLNode
{
    int i, j, e; //矩阵三元组i代表行 j代表列 e代表当前位置的数据
    struct OLNode *right, *down; //指针域 右指针 下指针
}OLNode, *OLink;
typedef struct
{
    OLink *rhead, *chead; //行和列链表头指针
    int mu, nu, tu;  //矩阵的行数,列数和非零元的个数
}CrossList;
CrossList CreateMatrix_OL(CrossList M);
void display(CrossList M);
int main()
{
    CrossList M;
    M.rhead = NULL;
    M.chead = NULL;
    M = CreateMatrix_OL(M);
    printf("输出矩阵M:\n");
    display(M);
    return 0;
}
CrossList CreateMatrix_OL(CrossList M)
{
    int m, n, t;
    int i, j, e;
    OLNode *p, *q;
    printf("输入矩阵的行数、列数和非0元素个数:");
    scanf("%d%d%d", &m, &n, &t);
    M.mu = m;
    M.nu = n;
    M.tu = t;
    if (!(M.rhead = (OLink*)malloc((m + 1) * sizeof(OLink))) || !(M.chead = (OLink*)malloc((n + 1) * sizeof(OLink))))
    {
        printf("初始化矩阵失败");
        exit(0);
    }
    for (i = 1; i <= m; i++)
    {
        M.rhead[i] = NULL;
    }
    for (j = 1; j <= n; j++)
    {
        M.chead[j] = NULL;
    }
    for (scanf("%d%d%d", &i, &j, &e); 0 != i; scanf("%d%d%d", &i, &j, &e)) {
        if (!(p = (OLNode*)malloc(sizeof(OLNode))))
        {
            printf("初始化三元组失败");
            exit(0);
        }
        p->i = i;
        p->j = j;
        p->e = e;
        //链接到行的指定位置
        if (NULL == M.rhead[i] || M.rhead[i]->j > j)
        {
            p->right = M.rhead[i];
            M.rhead[i] = p;
        }
        else
        {
            for (q = M.rhead[i]; (q->right) && q->right->j < j; q = q->right);
            p->right = q->right;
            q->right = p;
        }
        //链接到列的指定位置
        if (NULL == M.chead[j] || M.chead[j]->i > i)
        {
            p->down = M.chead[j];
            M.chead[j] = p;
        }
        else
        {
            for (q = M.chead[j]; (q->down) && q->down->i < i; q = q->down);
            p->down = q->down;
            q->down = p;
        }
    }
    return M;
}
void display(CrossList M) {
    for (int i = 1; i <= M.nu; i++)
    {
        if (NULL != M.chead[i])
        {
            OLink p = M.chead[i];
            while (NULL != p)
            {
                printf("%d\t%d\t%d\n", p->i, p->j, p->e);
                p = p->down;
            }
        }
    }
}

矩阵压缩

特殊矩阵的压缩存储
1.对称矩阵的压缩存储:
存n*(n+1)/2个元素
访问元素的方法:k = i (i-1)/2 + j -1.
2.三角矩阵的压缩存储:
存n
(n+1)/2+1个元素
访问元素的方法:k = (i - 1)*(2n-i+2)/2+j-i
3.对角矩阵的压缩存储:
K = 2i+j-3
4.稀疏矩阵的压缩存储

树和二叉树

优先队列

#include<iostream>
using namespace std;
const int QueueSize = 100;
class PriQueue
{
public:
    PriQueue();
    ~PriQueue();
    void EnQueue(int x); //入队操作
    int DeQueue();//出队操作
    int GetQueue();
    int Empty();
private:
    int data[QueueSize];
    int rear; //游标,队尾指针
};
PriQueue :: PriQueue()
{
    rear = 0;
}
PriQueue :: ~PriQueue()
{
}
int PriQueue :: GetQueue()
{
    return data[1];
}
int PriQueue :: Empty()
{
    if(rear == 0)
        return 1;
    else
        return 0;
}
void PriQueue :: EnQueue(int x)
{
    if(rear == QueueSize - 1)
        throw "上溢异常";
    int temp, i;
    i = ++rear;
    data[i] = x;
    while(i/2 > 0 && data[i/2] < x)
    {
        temp = data[i];
        data[i] = data[i/2];
        data[i/2] = temp;
        i = i/2;
    }
}
int PriQueue :: DeQueue()
{
    if(rear == 0)
        throw "上溢异常";
    int temp, x, i, j; //temp用于交换变量、x用于返回值,i父节点,j孩子结点
    x = data[1];
    data[1] = data[rear--];
    i = 1;
    j = 2*i;
    while(j <= rear)
    {
        if(j < rear && data[j] < data[j+1])
            j++; //选出两者中较大的值
        if(data[i] > data[j])
            break;
        else
        {
            temp = data[i];
            data[i] = data[j];
            data[j] = temp;
            i = j;
            j = 2 * i;
        }
    }
    return x;
}

int main()
{
    /**  */
    PriQueue p{ };
    p.EnQueue(30);
    p.EnQueue(22);
    p.EnQueue(18);
    p.EnQueue(32);
    p.EnQueue(36);
    p.EnQueue(45);
    p.EnQueue(40);
    p.EnQueue(50);
    cout << "队头元素是:" << p.GetQueue() << endl;
   cout << p.DeQueue();
    cout << endl;
    cout << p.DeQueue();
    cout << endl;
    cout << "出队两个元素后,队头元素是:" << p.GetQueue() << endl;
    return 0;
}

优先队列使用详解点击这里

二叉链表的遍历

/*************************************************
二叉链表类BiTree的使用范例
**************************************************/
#include<iostream>
using namespace std;

template<typename DataType>
struct BiNode
{
    DataType data;
    BiNode *lchild, *rchild;
};

template<typename DataType>
class BiTree
{
public:
    BiTree( )
    {
        root = Creat(root);   //构造函数,建立一棵二叉树
    }
    ~BiTree( )
    {
        Release(root);   //析构函数,释放各结点的存储空间
    }
    void PreOrder( )
    {
        PreOrder(root);   //前序遍历二叉树
    }
    void InOrder( )
    {
        InOrder(root);   //中序遍历二叉树
    }
    void PostOrder( )
    {
        PostOrder(root);   //后序遍历二叉树
    }
    void LeverOrder( ); //层序遍历二叉树
private:
    BiNode <DataType>*Creat(BiNode<DataType> *bt); //构造函数调用
    void Release(BiNode<DataType> *bt); //析构函数调用
    void PreOrder(BiNode<DataType> *bt); //前序遍历函数调用
    void InOrder(BiNode<DataType> *bt); //中序遍历函数调用
    void PostOrder(BiNode<DataType> *bt); //后序遍历函数调用

    BiNode<DataType> *root; //指向根结点的头指针
};

template<typename DataType>
void BiTree<DataType>:: PreOrder(BiNode<DataType> *bt)
{
    if (bt == nullptr) return; //递归调用的结束条件
    else
    {
        cout << bt->data; //访问根结点bt的数据域
        PreOrder(bt->lchild); //前序递归遍历bt的左子树
        PreOrder(bt->rchild); //前序递归遍历bt的右子树
    }
}

template<typename DataType>
void BiTree<DataType>:: InOrder(BiNode<DataType> *bt)
{
    if (bt == nullptr) return; //递归调用的结束条件
    else
    {
        InOrder(bt->lchild); //前序递归遍历bt的左子树
        cout << bt->data; //访问根结点bt的数据域
        InOrder(bt->rchild); //前序递归遍历bt的右子树
    }
}

template<typename DataType>
void BiTree<DataType>:: PostOrder(BiNode<DataType> *bt)
{
    if (bt == nullptr) return; //递归调用的结束条件
    else
    {
        InOrder(bt->lchild); //前序递归遍历bt的左子树
        InOrder(bt->rchild); //前序递归遍历bt的右子树
        cout << bt->data; //访问根结点bt的数据域
    }
}

template<typename DataType>
void BiTree<DataType>:: LeverOrder( )
{
    BiNode<DataType> *Q[100], *q = nullptr; //顺序队列最多100个结点
    int front = -1, rear = -1; //队列初始化
    if (root == nullptr) return; //二叉树为空,算法结束
    Q[++rear] = root; //根指针入队
    while (front != rear) //当队列非空时
    {
        q = Q[++front]; //出队
        cout << q->data;
        if (q->lchild != nullptr) Q[++rear] = q->lchild;
        if (q->rchild != nullptr) Q[++rear] = q->rchild;
    }
}

template<typename DataType>
BiNode<DataType> *BiTree <DataType>:: Creat(BiNode<DataType> *bt)
{
    char ch;
    cout << "请输入扩展二叉树的前序遍历序列,每次输入一个字符:";
    cin >> ch; //输入结点的数据信息,假设为字符
    if (ch == '#') bt = nullptr; //建立一棵空树
    else
    {
        bt = new BiNode<DataType>;
        bt->data = ch;
        bt->lchild = Creat(bt->lchild); //递归建立左子树
        bt->rchild = Creat(bt->rchild); //递归建立右子树
    }
    return bt;
}

template<typename DataType>
void BiTree<DataType>:: Release(BiNode<DataType> *bt)
{
    if (bt == nullptr) return;
    else
    {
        Release(bt->lchild); //释放左子树
        Release(bt->rchild); //释放右子树
        delete bt; //释放根结点
    }
}

int main( )
{
    BiTree<char> T{}; //定义对象变量T
    cout << "该二叉树的前序遍历序列是:";
    T.PreOrder( );
    cout << "\n该二叉树的中序遍历序列是:";
    T.InOrder( );
    cout << "\n该二叉树的后序遍历序列是:";
    T.PostOrder( );
    cout << "\n该二叉树的层序遍历序列是:";
    T.LeverOrder( );
    return 0;
}

邻接表

/************************************************
邻接表类ALGraph的使用范例
*************************************************/
#include<iostream>
using namespace std;

struct EdgeNode //定义边表结点
{
    int adjvex; //邻接点域
    EdgeNode *next;
};

template <typename DataType>
struct VertexNode //定义顶点表结点
{
    DataType vertex;
    EdgeNode *firstEdge;
};

const int MaxSize = 10; //图的最多顶点数
int visited[MaxSize] = {0};
template  <typename DataType>
class ALGraph
{
public:
    ALGraph(DataType a[ ], int n, int e); //构造函数,建立n个顶点e条边的图
    ~ALGraph( ); //析构函数,释放邻接表各边表结点的存储空间
    void DFTraverse(int v); //深度优先遍历图
    void BFTraverse(int v); //广度优先遍历图
private:
    VertexNode<DataType> adjlist[MaxSize]; //存放顶点表的数组
    int vertexNum, edgeNum; //图的顶点数和边数
};

template <typename DataType>
ALGraph<DataType> :: ALGraph(DataType a[ ], int n, int e)
{
    int i, j, k;
    EdgeNode *s = nullptr;
    vertexNum = n;
    edgeNum = e;
    for (i = 0; i < vertexNum; i++) //输入顶点信息,初始化顶点表
    {
        adjlist[i].vertex = a[i];
        adjlist[i].firstEdge = NULL;
    }
    for (k = 0; k < edgeNum; k++) //依次输入每一条边
    {
        cout << "输入边所依附的两个顶点的编号:";
        cin >> i >> j; //输入边所依附的两个顶点的编号
        s = new EdgeNode;
        s->adjvex = j; //生成一个边表结点s
        s->next = adjlist[i].firstEdge; //将结点s插入到第i个边表的表头
        adjlist[i].firstEdge = s;
    }
}

template <typename DataType>
ALGraph<DataType>  :: ~ALGraph( )
{
    EdgeNode *p = NULL, *q = NULL;
    for (int i = 0; i < vertexNum; i++)
    {
        p = q = adjlist[i].firstEdge;
        while (p != NULL)
        {
            p = p->next;
            delete q;
            q = p;
        }
    }
}

template  <typename DataType>
void ALGraph<DataType>  :: DFTraverse(int v)
{
    int j;
    EdgeNode *p = NULL;
    cout << adjlist[v].vertex;
    visited[v] = 1;
    p = adjlist[v].firstEdge; //工作指针p指向顶点v的边表
    while (p != NULL) //依次搜索顶点v的邻接点
    {
        j = p->adjvex;
        if (visited[j] == 0) DFTraverse(j);
        p = p->next;
    }
}

template <typename DataType>
void ALGraph<DataType> :: BFTraverse(int v)
{
    int w, j, Q[MaxSize]; //采用顺序队列
    int front = -1, rear = -1; //初始化队列
    EdgeNode *p = nullptr;
    cout << adjlist[v].vertex;
    visited[v] = 1;
    Q[++rear] = v; //被访问顶点入队
    while (front != rear) //当队列非空时
    {
        w = Q[++front];
        p = adjlist[w].firstEdge; //工作指针p指向顶点v的边表
        while (p != NULL)
        {
            j = p->adjvex;
            if (visited[j] == 0)
            {
                cout << adjlist[j].vertex;
                visited[j] = 1;
                Q[++rear] = j;
            }
            p = p->next;
        }
    }
}

int main( )
{
//测试数据是图6-20(a),边是(0 1)(0 3)(0 4)(1 2)(2 4)(3 2)(3 4)
    char ch[ ] = {'A','B','C','D','E'};
    int i;
    ALGraph<char> ALG(ch, 5, 6); //建立具有5个顶点6条边的有向图
    for (i = 0; i < MaxSize; i++)
        visited[i] = 0;
    cout << "深度优先遍历序列是:";
    ALG.DFTraverse(0); //从顶点0出发进行深度优先遍历
    for (i = 0; i < MaxSize; i++)
        visited[i] = 0;
    cout << "广度优先遍历序列是:";
    ALG.BFTraverse(0); //从顶点0出发进行广度优先遍历
    return 0;
}

邻接矩阵

/************************************************
邻接矩阵类MGraph的使用范例
*************************************************/
#include<iostream>
using namespace std;

const int MaxSize = 10; //图中最多顶点个数
int visited[MaxSize] = {0}; //全局数组变量visited初始化
template <typename DataType>
class MGraph
{
public:
    MGraph(DataType a[ ], int n, int e); //构造函数,建立具有n个顶点e条边的图
    ~MGraph( ) { }; //析构函数
    void DFTraverse(int v); //深度优先遍历图
    void BFTraverse(int v); //广度优先遍历图
private:
    DataType vertex[MaxSize]; //存放图中顶点的数组
    int edge[MaxSize][MaxSize]; //存放图中边的数组
    int vertexNum, edgeNum; //图的顶点数和边数
};

template<typename DataType>
MGraph <DataType>:: MGraph(DataType a[ ], int n, int e)
{
    int i, j, k;
    vertexNum = n;
    edgeNum = e;
    for (i = 0; i < vertexNum; i++) //存储顶点
        vertex[i] = a[i];
    for (i = 0; i < vertexNum; i++) //初始化邻接矩阵
        for (j = 0; j < vertexNum; j++)
            edge[i][j] = 0;
    for (k = 0; k < edgeNum; k++) //依次输入每一条边
    {
        cout << "请输入边依附的两个顶点的编号:";
        cin >> i >> j; //输入边依附的两个顶点的编号
        edge[i][j] = 1;
        edge[j][i] = 1; //置有边标志
    }
}

template<typename DataType>
void MGraph <DataType>:: DFTraverse(int v)
{
    cout << vertex[v];
    visited[v] = 1;
    for (int j = 0; j < vertexNum; j++)
        if (edge[v][j] == 1 && visited[j] == 0) DFTraverse( j );
}

template<typename DataType>
void MGraph <DataType>:: BFTraverse(int v)
{
    int w, j, Q[MaxSize]; //采用顺序队列
    int front = -1, rear = -1; //初始化队列
    cout << vertex[v];
    visited[v] = 1;
    Q[++rear] = v; //被访问顶点入队
    while (front != rear) //当队列非空时
    {
        w = Q[++front]; //将队头元素出队并送到v中
        for (j = 0; j < vertexNum; j++)
            if (edge[w][j] == 1 && visited[j] == 0 )
            {
                cout << vertex[j];
                visited[j] = 1;
                Q[++rear] = j;
            }
    }
}

int main( )
{
    int i;
    char ch[ ]= {'A','B','C','D','E'};
    /* 测试数据六条边是:(0 1)(0 2)(0 3)(0 4)(1 2)(2 4) */
    MGraph<char> MG{ch, 5, 6}; //建立具有5个顶点6条边的无向图
    for (i = 0; i < MaxSize; i++)
        visited[i] = 0;
    cout << "深度优先遍历序列是:" << endl;
    MG.DFTraverse(0); //从顶点0出发进行深度优先遍历
    for (i = 0; i < MaxSize; i++)
        visited[i] = 0;
    cout << "广度优先遍历序列是:" << endl;
    MG.BFTraverse(0); //从顶点0出发进行广度优先遍历
    return 0;
}

查找

二叉排序树

#include<iostream>
using namespace std;
struct BiNode
{
    int data;
    BiNode *lchild, *rchild;
};
class BiSortTree
{
public:
    BiSortTree(int a[ ], int n); //建立查找集合a[n]的二叉排序树
    ~ BiSortTree( )
    {
        Release(root);    //析构函数,同二叉链表的析构函数
    }
    void InOrder( )
    {
        InOrder(root);   //中序遍历二叉树
    }
     int GetDepth();
    BiNode *InsertBST(int x)
    {
        return InsertBST(root, x);   //插入记录x
    }
    void DeleteBST(BiNode *p, BiNode *f ); //删除f的左孩子p
    BiNode *SearchBST(int k)
    {
        return SearchBST(root, k);   //查找值为k的结点
    }

private:
    int GetDepth(BiNode *&bt);
    void Release(BiNode *bt);
    BiNode *InsertBST(BiNode *bt, int x);
    BiNode *SearchBST(BiNode*bt, int k);
    void InOrder(BiNode *bt); //中序遍历函数调用

    BiNode *root; //二叉排序树的根指针
};

void BiSortTree :: InOrder(BiNode *bt)
{
    if (bt == nullptr)
        return; //递归调用的结束条件
    else
    {
        InOrder(bt->lchild); //前序递归遍历bt的左子树
        cout << bt->data << " "; //访问根结点bt的数据域
        InOrder(bt->rchild); //前序递归遍历bt的右子树
    }
}

BiNode * BiSortTree :: SearchBST(BiNode *bt, int k)
{
    if (bt == nullptr)
        return nullptr;
    if (bt->data == k)
        return bt;
    else if (bt->data > k)
        return SearchBST(bt->lchild, k);
    else
        return SearchBST(bt->rchild, k);
}

BiNode *BiSortTree::InsertBST(BiNode*bt, int x)
{
    if (bt == nullptr)   //找到插入位置
    {
        BiNode *s = new BiNode;
        s->data = x;
        s->lchild = nullptr;
        s->rchild = nullptr;
        bt = s;
        return bt;
    }
    else if (bt->data > x)
        bt->lchild = InsertBST(bt->lchild, x);
    else
        bt->rchild = InsertBST(bt->rchild, x);
}

BiSortTree::BiSortTree(int a[ ], int n)
{
    root = nullptr;
    for (int i = 0; i < n; i++)
        root = InsertBST(root, a[i]);
}

void BiSortTree::DeleteBST(BiNode *p, BiNode *f )
{
    if ((p->lchild == nullptr) && (p->rchild == nullptr))   //p为叶子
    {
        f->lchild = nullptr;
        delete p;
        return;
    }
    if (p->rchild == nullptr)   //p只有左子树
    {
        f->lchild = p->lchild;
        delete p;
        return;
    }
    if (p->lchild == nullptr)   //p只有右子树
    {
        f->lchild = p->rchild;
        delete p;
        return;
    }
    BiNode *par = p, *s = p->rchild; //p的左右子树均不空
    while (s->lchild != nullptr) //查找最左下结点
    {
        par = s;
        s = s->lchild;
    }
    p->data = s->data;
    if (par == p)
        par->rchild = s->rchild; //特殊情况,p的右孩子无左子树
    else
        par->lchild = s->rchild;
    delete s;
}

void BiSortTree:: Release(BiNode *bt)
{
    if (bt == nullptr)
        return;
    else
    {
        Release(bt->lchild); //释放左子树
        Release(bt->rchild); //释放右子树
        delete bt; //释放根结点
    }
}

int BiSortTree::GetDepth()
{
    int nMax = GetDepth(root);
    return nMax;
}

int BiSortTree::GetDepth(BiNode *&bt)
{
    if(nullptr == bt) return 0;
    int nL = GetDepth(bt->lchild);
    int nR = GetDepth(bt->rchild);
    int nMax = nL > nR ? nL : nR;
    nMax += 1;
    return nMax;
}
int main( )
{
    BiNode *p = nullptr;
    int arr[10] = {1,2, 3, 4, 5, 6, 7, 8, 9, 10};
    BiSortTree B{arr,10};
    B.InOrder();
    int key;
    cout << "请输入查找的元素值";
    cin >> key;
    p = B.SearchBST(key);
    if (p != nullptr)
        cout << p->data << endl;
    else
        cout << "查找失败" << endl;
    cout<<B.GetDepth() << endl;
    system("pause");
    return 0;

}

平衡二叉树

/***************************************************************
二叉排序树的类定义、成员函数定义及使用范例
****************************************************************/
#include<iostream>
using namespace std;
typedef struct biNode
{
    int data;
    biNode *lchild, *rchild;
}*BiNode,BiNodes;
struct biNode biNode = {0x3f,NULL,NULL};
class BiSortTree
{
public:
    BiSortTree(int a[ ], int n); //建立查找集合a[n]的二叉排序树
    ~ BiSortTree( )
    {
        Release(root);    //析构函数,同二叉链表的析构函数
    }
    void InOrder( )
    {
        InOrder(root);   //中序遍历二叉树
    }

    bool InsertBST(int x);
    int GetDepth();
    void DeleteBST(BiNode p, BiNode f ); //删除f的左孩子p
    BiNode SearchBST(int k)
    {
        return SearchBST(root, k);   //查找值为k的结点
    }
private:
    void Release(BiNode bt);
    int GetDepth(BiNode &bt);
    bool InsertBST(BiNode &bt, int x);
    BiNode SearchBST(BiNode bt, int k);
    void InOrder(BiNode bt); //中序遍历函数调用
    BiNode root; //二叉排序树的根指针
    //平衡函数
    void SingRotateLeft(BiNode &pK2);//LL
    void SingRotateRight(BiNode &pK2);//RR
    void DoubleRotateLR(BiNode &pK);//LR
    void DoubleRotateRL(BiNode &pK);//RL
};

void BiSortTree :: InOrder(BiNode bt)
{
    if (bt == nullptr)
        return; //递归调用的结束条件
    else
    {
        InOrder(bt->lchild); //前序递归遍历bt的左子树
        cout << bt->data << " "; //访问根结点bt的数据域
        InOrder(bt->rchild); //前序递归遍历bt的右子树
    }
}

BiNode  BiSortTree :: SearchBST(BiNode bt, int k)
{
    if (bt == nullptr)
        return nullptr;
    if (bt->data == k)
        return bt;
    else if (bt->data > k)
        return SearchBST(bt->lchild, k);
    else
        return SearchBST(bt->rchild, k);
}
/********************
最核心的部分,
因为参数是指针的引用,
在每次插入元素过后,
回溯的时候都会对当前结点的左右子树的深度进行判定。
*********************/
bool BiSortTree::InsertBST(BiNode &bt, int x)
{
    if (bt == nullptr)   //找到插入位置
    {
        BiNodes *s = new BiNodes;
        s->data = x;
        s->lchild = nullptr;
        s->rchild = nullptr;
        bt = s;
        return true;
    }
    if(x > bt->data)
    {
        InsertBST(bt->rchild,x);
        if(GetDepth(bt->rchild)-GetDepth(bt->lchild)==2)
            if(GetDepth(bt->rchild->lchild)>GetDepth(bt->rchild->rchild))
                DoubleRotateRL(bt);
            else SingRotateLeft(bt);
    }
    if(x < bt->data)
    {
        InsertBST(bt->lchild,x);
        if(GetDepth(bt->lchild)-GetDepth(bt->rchild)==2)//????
            if(GetDepth(bt->lchild->rchild)>GetDepth(bt->lchild->lchild))
                 DoubleRotateLR(bt);
            else SingRotateRight(bt);
    }
}
bool BiSortTree::InsertBST(int x)
{
    if(InsertBST(root,x))return true;
    return false;
}
BiSortTree::BiSortTree(int a[ ], int n)
{
    root = nullptr;
    for (int i = 0; i < n; i++)
        InsertBST(root, a[i]);
}
void BiSortTree::DeleteBST(BiNode p, BiNode f )
{
    if ((p->lchild == nullptr) && (p->rchild == nullptr))   //p为叶子
    {
        f->lchild = nullptr;
        delete p;
        return;
    }
    if (p->rchild == nullptr)   //p只有左子树
    {
        f->lchild = p->lchild;
        delete p;
        return;
    }
    if (p->lchild == nullptr)   //p只有右子树
    {
        f->lchild = p->rchild;
        delete p;
        return;
    }
    BiNode par = p, s = p->rchild; //p的左右子树均不空
    while (s->lchild != nullptr) //查找最左下结点
    {
        par = s;
        s = s->lchild;
    }
    p->data = s->data;
    if (par == p)
        par->rchild = s->rchild; //特殊情况,p的右孩子无左子树
    else
        par->lchild = s->rchild;
    delete s;
}
void BiSortTree :: Release(BiNode bt)
{
    if (bt == nullptr)
        return;
    else
    {
        Release(bt->lchild); //释放左子树
        Release(bt->rchild); //释放右子树
        delete bt; //释放根结点
    }
}
int BiSortTree::GetDepth()
{
    int nMax = GetDepth(root);
    return nMax;
}
int BiSortTree::GetDepth(BiNode &bt)
{
    if(nullptr == bt) return 0;
    int nL = GetDepth(bt->lchild);
    int nR = GetDepth(bt->rchild);
    int nMax = nL > nR ? nL : nR;
    nMax += 1;
    return nMax;
}
/***
RR
***/
void BiSortTree::SingRotateLeft(BiNode &bt2)
{
    BiNode bt1 = bt2 -> rchild;
    bt2 -> rchild = bt1->lchild;
    bt1 -> lchild = bt2;
    bt2 = bt1;
}
/***
LL
***/
void BiSortTree::SingRotateRight(BiNode &bt2)
{
    BiNode bt1 = bt2 -> lchild;
    bt2 -> lchild = bt1->rchild;
    bt1 -> rchild = bt2;
    bt2 = bt1;
}
/***
RL
***/
void BiSortTree::DoubleRotateRL(BiNode &bt3)
{
    SingRotateRight(bt3 -> rchild);
    SingRotateLeft(bt3);
}
/***
LR
***/
void BiSortTree::DoubleRotateLR(BiNode &bt3)
{
    SingRotateLeft(bt3->lchild);
    SingRotateRight(bt3);

}
int main( )
{
  int arr[10] = {1,2, 3, 4, 5, 6, 7, 8, 9, 10};
   BiSortTree B{arr,10};
   B.InOrder();
   cout << B.GetDepth()<<endl;;
   return 0;

}

排序

桶排序

#include <iostream>
#include <cstring>
using namespace std;
void bucketSort(int* a, int n, int max)
{
    int i, j;
    int *buckets;
    if (a==NULL || n<1 || max<1)
        return ;
    // 创建一个容量为max的数组buckets,并且将buckets中的所有数据都初始化为0。
    if ((buckets = new int[max])==NULL)
        return ;
    memset(buckets, 0, max*sizeof(int));
    // 1. 计数
    for(i = 0; i < n; i++)
        buckets[a[i]]++;
    // 2. 排序
    for (i = 0, j = 0; i < max; i++)
        while( (buckets[i]--) >0 )
            a[j++] = i;
    delete[] buckets;
}
int main()
{
    int i;
    int a[] = {8,2,3,4,3,6,6,3,9};
    int ilen = (sizeof(a)) / (sizeof(a[0]));
    cout << "before sort:";
    for (i=0; i<ilen; i++)
        cout << a[i] << " ";
    cout << endl;
    bucketSort(a, ilen, 10); // 桶排序
    cout << "after  sort:";
    for (i=0; i<ilen; i++)
        cout << a[i] << " ";
    cout << endl;
    return 0;
}

持续更新

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

dearzcs

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

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

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

打赏作者

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

抵扣说明:

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

余额充值