数据结构——代码(第二,三章)

数据结构代码参考

第二章(链表)

1.顺序链表

//顺序表
/*   静态分配 
#include<stdio.h>
#define MaxSize 10 //定义最大长度 
typedef struct{
	int data[MaxSize]; //用静态数组存放数据元素 
	int length;//顺序表当前的长度 
}SqList;//顺序表的类型定义 

void InitList(&L)//初始化顺序表 
{
	L.length=0;
}
*/
//动态分配
#include<stdio.h>
#include<stdlib.h> 
#define ElemType int 
#define InitSize 10 //默认的最大长度 
typedef struct{
	ElemType * data; //指示动态分配数组的指针 
	int length; //顺序表当前的长度 
	int MaxSize; //顺序表最大的容量 
}SqList;//顺序表的类型定义

//1.初始化顺序表 
void InitList(SqList &L)
{
	//用malloc 函数申请一片连续的存储空间 
	L.data=(ElemType *)malloc(InitSize*sizeof(ElemType));
	L.length=0;
	L.MaxSize=InitSize;
}
//2.动态增加数组的长度
void IncreaseSize(SqList &L, int len)
{
	ElemType * q=L.data;
	L.data=(ElemType *)malloc((L.MaxSize+len)*sizeof(ElemType));
	for(int i=0;i<L.length;++i)
	{
		L.data[i]=q[i]; //将数据复制到新的区域 
	}
	L.MaxSize+=len;//顺序表最大长度增加 len 
	free(q);	//释放原来的空间 
} 
//3.插入顺序表 
bool ListInsert(SqList &L,int i,ElemType e)
{
	if(i<1||i>L.length+1)//判断i的范围是否有效 
	{
		return false;
	}
	if(i>L.MaxSize)//当前存储空间已满,不能再插入 
	{
		return false;
	}
	for(int j=L.length;i<=j;--j)//将第i个元素及之后的元素后移 
	{
		L.data[j]=L.data[j-1];
	}
	L.data[i-1]=e;//在位置i出放入e 
	L.length++;//长度加1 
	return true; 
} 
//3.删除顺序表
bool ListDelete(SqList &L,int i,ElemType &e)
{
	if(i<1||i>L.length)//判断i的范围是否有效 
	{
		return false;
	}
	e=L.data[i-1];//将被删除的元素赋值给e 
	for(int j=i;j<L.length;++j)
	{
		L.data[j-1]=L.data[j];//将第i个位置后的元素前移 
	} 
	L.length--;
	return true;
} 
//4.查找顺序表
ElemType GetElem_1(SqList &L,int i)
{
	return L.data[i-1];
} 
int GetElem_2(SqList &L,ElemType e)
{
	for(int i=0;i<L.length;++i)
	{
		if(L.data[i]==e)
		{
			return i+1;
		}
	}
	return 0;
} 
//5.输出顺序表
void ShowList(SqList &L)
{
	for(int i=0;i<L.length;++i)
	{
		printf("%d",L.data[i]);
		printf(" ");
	}
	printf("\n");
} 
int main()
{
	SqList L; //申明一个顺序表 
	InitList(L);//初始化顺序表 
	//往顺序表填入数据 
	for(int i=0;i<L.MaxSize;i++)
	{
		L.data[i]=i+1;
		L.length++;
	}
	IncreaseSize(L,5);//动态增加数组的长度 
	ListInsert(L,3,0);//插入顺序表
	ElemType e=L.data[0];//初始化e 
	ListDelete(L,3,e);//删除顺序表 
	ShowList(L);//输出顺序表 
	printf("%d",GetElem_2(L,10));//按值查找 
 
	return 0;
} 

2.链式表

 // 带头结点点与不带头节点的异同
// 异: 1.对第一结点的操作处理不同,不带头节点需要单独处理。其余相同
//      2.结点按序定位的差别,相差为1 (带头节点 j=0)(不带头节点 j=1)

#include <iostream>
using namespace std;
#include <stdio.h>
#include <stdlib.h>
#define ElemType int
// 1.定义单链表数据类型
typedef struct LNode
{
    ElemType data;      // 每个结点存放一个数据元素
    struct LNode *next; // 指针指向下一个结点
} LNode, *LinkList;
// 2.初始化单链表(带头节点)
bool InitList_1(LinkList &L)
{
    L = (LNode *)malloc(sizeof(LNode));
    if (L == NULL) // 内存不足,分配失败
    {
        return false;
    }
    L->next = NULL; // 头结点之后暂时还没有结点
    L->data = 0;    // 头节点没有数据
    return true;
}
// 2.初始化单链表(不带头节点)
bool InitList_2(LinkList &L)
{
    L = NULL; // 空表,暂时还没有任何数据
    return true;
}
// 3.判断表(带头结点)是否为空
bool Empty_1(LinkList &L)
{
    if (L->next == NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}
// 3.判断表(不带头节点)是否为空
bool Empty_2(LinkList &L)
{
    if (L == NULL)
    {
        return true;
    }
    else
    {
        return false;
    }
}
// 4.指定结点后插操作:在P结点后插入元素e
bool InsertNextNode(LNode *p, ElemType e)
{
    if (p == NULL)
    {
        return false;
    }
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if (s == NULL)
    {
        return false; // malloc分配空间失败
    }
    s->data = e;
    s->next = p->next;
    p->next = s;
    return true;
}
// 4.指定结点前插操作:在P结点前插元素e
// a.单链表的特性,指定结点的前端结点都是神秘不可访问的 因此通过传入头节点
// bool insertPriorNode(linkList L,LNode *p,ElemType e)
// b.巧妙地元素复制移位
bool InsertPriorNode(LNode *p, ElemType e)
{
    if (p == NULL)
    {
        return false;
    }
    LNode *s = (LNode *)malloc(sizeof(LNode));
    if (s == NULL)
    {
        return false; // malloc分配空间失败
    }
    s->data = p->data;
    s->next = p->next;
    p->next = s;
    p->data = e;
    return true;
}
// 5.找到第i个结点的位置(带头节点)
LNode *NodeLocation(LinkList &L, int i)
{
    if (i < 1)
    {
        return NULL;
    }
    LNode *p = L;              // p指向当前扫描到的结点 初始指向头节点
    int j = 0;                 // 当前p指向的第几个结点
    while (p != NULL && j < i) // 循环找到第i-1个结点
    {
        p = p->next;
        j++;
    }
    return p;
}
// 5.找到第i个结点的位置(不带头节点)
LNode *NodeLocation_2(LinkList &L, int i)
{
    if (i < 1)
    {
        return NULL;
    }
    LNode *p = L;              // p指向当前扫描到的结点 初始指向头节点
    int j = 1;                 // 当前p指向的第几个结点
    while (p != NULL && j < i) // 循环找到第i-1个结点
    {
        p = p->next;
        j++;
    }
    return p;
}
// 6.按位插入(带头节点)
bool ListInsert_1(LinkList &L, int i, ElemType e)
{
    // 1.找到要插入的位置前一个结点
    LNode *p = NodeLocation(L, i - 1);
    // 2.完成结点的插入
    InsertNextNode(p, e);
    return true;
}
// 6.按位插入(不带头节点)
bool ListInsert_2(LinkList &L, int i, ElemType e)
{
    if (i <= 0)
    {
        return false;
    }
    else if (i == 1)
    {
        LNode *p = (LNode *)malloc(sizeof(LNode));
        p->next = L;
        L = p;
        p->data = e;
        return true;
    }
    else
    {
        // 1.找到要插入的位置前一个结点
        LNode *p = NodeLocation(L, i - 1);
        // 2.完成结点的插入
        InsertNextNode(p, e);
        return true;
    }
}
// 7.删除(带头节点)

// 按位序删除
bool ListDelete_1(LinkList &L, int i, ElemType &e)
{
    if (i < 1)
    {
        return false;
    }
    LNode *s = NodeLocation(L, i - 1); // 找到删除结点的前一个结点
    LNode *q = s->next;                // 删除结点的地址
    e = q->data;
    s->next = q->next;
    free(q); // 释放空间
    return true;
}

// 指定结点的删除
// (1).传入头指针 ,需要修改其前驱结点的next指针
// (2).偷天换日(类似于结点前插的实现)如果是最后一个结点 只能从头开始了
bool DeleteNode_1(LNode *p)
{
    if (p == NULL)
    {
        return false;
    }
    LNode *q = p->next; // 令q为指定删除结点的后继结点
    p->data = q->data;  // 和后继结点交换数据
    p->next = q->next;  // 将*q从单链表中断开
    free(q);            // 释放储存空间
    return true;
}

// 7.删除(不带头节点)

// 按位序删除
bool ListDelete_2(LinkList &L, int i, ElemType e)
{

    if (i == 1)
    {
        e = L->data;
        L->next = L;
        free(L);
        return 0;
    }
    if (i < 1)
    {
        return false;
    }
    // 此部分 同带节点一样只是定位的差异
    LNode *s = NodeLocation(L, i - 1); // 找到删除结点的前一个结点
    LNode *q = s->next;                // 删除结点的地址
    e = q->data;
    s->next = q->next;
    free(q); // 释放空间
    return true;
}

// 8.创建链表-带头节点 (头插法)
bool List_HeadInsert(LinkList &L)
{
    printf("请输入插入数据:\n");
    ElemType e;
    scanf("%d", &e);
    InsertNextNode(L, e);
    return true;
}
// 8.创建链表-带头节点 (尾插法)($$$$$$$$$$$$$)
bool List_Taillnsert(LinkList &L)
{
    printf("请输入插入数据:\n");
    ElemType e;
    scanf("%d", &e);
    LNode *p = L;
    if (Empty_1(L))
    {
        InsertNextNode(L, e); // 空链表直接后插 使其不为空链表
    }
    else
    {
        p = p->next;
        InsertPriorNode(p, e); // 非空链表 ,在第一个结点前插实现链表的逆序
    }
    return true;
}
// 9.按值查找
LNode *LocateElem(LinkList &L, ElemType &e)
{
    LNode *p = L->next; // 第一节点地址赋值给p
    while (p != NULL && p->data != e)
    {
        p = p->next;
    }
    return p;
}
// 10.求表长(带头节点)
int Length(LinkList &L)
{
    LNode *p = L;
    int len = 0;
    while (p != NULL)
    {
        p = p->next;
        len++;
    }
    return len;
}
// 11.输出单链表-带头节点
void showList(LinkList L)
{
    printf("链表为:");
    while (L->next != NULL)
    {
        L = L->next;
        printf("%d", (L->data));
        printf(" ");
    }
}
int main()
{
    LinkList L;     // 创建一个单链表
    InitList_1(L);  // 初始化带头节点的单链表
    if (Empty_1(L)) // 判断链表是否为空
    {
        printf("链表为空!\n");
    }
    else
    {
        printf("链表不为空!\n");
    }

    for (int i = 0; i < 5; ++i)
    {
        List_HeadInsert(L);
    }
    showList(L);

    ElemType e = 0;
    ListDelete_1(L, 5, e);
    showList(L);
    cout << endl;
    cout << e << endl;

    // 利用尾插 实现链表的逆序
    LinkList L1;     // 创建一个单链表
    InitList_1(L1);  // 初始化带头节点的单链表
    if (Empty_1(L1)) // 判断链表是否为空
    {
        printf("链表为空!\n");
    }
    else
    {
        printf("链表不为空!\n");
    }

    for (int i = 0; i < 5; ++i)
    {
        List_Taillnsert(L1);
    }
    showList(L1);
}

第三章(栈,队列和数组)

1.栈

1.顺序栈

#include <iostream>
#include <stdio.h>
#define MaxSize 50   // 栈的最大容量
#define Elemtype int // 栈的数据类型
using namespace std;

typedef struct
{
    Elemtype data[MaxSize]; // 存放栈中的元素
    int top;                // 记录栈顶指针
} SqStack;

// 1.初始化
void InitStake(SqStack &S)
{
    S.top = -1;
}
// 2.判断栈空
bool StackEmpty(SqStack S)
{
    if (S.top == -1)
    {
        return true;
    }
    else
    {
        return false;
    }
}
// 3.进栈
bool PushStack(SqStack &S, Elemtype x)
{
    if (S.top == MaxSize - 1) // 栈满
    {
        return false;
    }
    S.data[++S.top] = x;
    return true;
}
// 4.出栈
bool PopStack(SqStack &S, Elemtype &x)
{
    if (StackEmpty(S)) // 栈空
    {
        return false;
    }
    x = S.data[S.top--];
    return true;
}
// 5.读取栈顶元素
bool GetStack(SqStack S, Elemtype &x)
{
    if (StackEmpty(S)) // 栈空
    {
        return false;
    }
    x = S.data[S.top];
    return true;
}
int main()
{
    SqStack S;    // 申明栈时就创建地址空间
    InitStake(S); // 初始化
    // 压栈26个元素0~25
    for (int i = 0; i < 26; ++i)
    {
        PushStack(S, i);
    }
    Elemtype x;
    GetStack(S, x); // 获得栈顶元素
    cout << x << endl;
    return 0;
}

2.共享栈

#include <iostream>
#include <stdio.h>
#define MaxSize 50   // 栈的最大容量
#define Elemtype int // 栈的数据类型
using namespace std;

typedef struct
{
    Elemtype data[MaxSize]; // 存放栈中的元素
    int top_0;              // 记录栈顶指针
    int top_1;
} SqStack;

// 1.初始化
void InitStake(SqStack &S)
{
    S.top_0 = -1;
    S.top_1 = MaxSize;
}
// 2.判断栈空
bool StackEmpty(SqStack S)
{
    if (S.top_0 == -1 && S.top_1 == MaxSize)
    {
        return true;
    }
    else
    {
        return false;
    }
}
// 3.进栈
bool PushStack(SqStack &S, Elemtype x, int a)
{
    if (S.top_0 + 1 == S.top_1) // 栈满
    {
        return false;
    }
    if (a == 0)
    {
        S.data[++S.top_0] = x;
    }
    else
    {
        S.data[--S.top_1] = x;
    }

    return true;
}
// 4.出栈
bool PopStack(SqStack &S, Elemtype &x, int a)
{
    if (StackEmpty(S)) // 栈空
    {
        return false;
    }
    if (a == 0)
    {
        x = S.data[S.top_0--];
    }
    else
    {
        x = S.data[S.top_1++];
    }

    return true;
}
// 5.读取栈顶元素
bool GetStack(SqStack S, Elemtype &x, int a)
{
    if (StackEmpty(S)) // 栈空
    {
        return false;
    }
    if (a == 0)
    {
        x = S.data[S.top_0];
    }
    else
    {
        x = S.data[S.top_1];
    }
    return true;
}
int main()
{
    SqStack S;    // 申明栈时就创建地址空间
    InitStake(S); // 初始化
    // 压栈26个元素0~25
    for (int i = 0; i < 26; ++i)
    {
        PushStack(S, i, 1);
    }
    Elemtype x;
    GetStack(S, x, 1); // 获得栈顶元素
    cout << x << endl;
    return 0;
}

3.练习题

a.P70:04

P70:04——设单链表的表头指针为L,结点结构由data和next两个区域组成,其中data是字符型。设计算法判断该链表的全部n个字符是否中心对称例如:xyx,xyyx.

  • 不带头节点的单链表:
#include <iostream>
#include <stdio.h>
#include <string.h>
#define Elemtype char // 栈的数据类型
using namespace std;

typedef struct LinkNode
{
    Elemtype data;
    struct LinkNode *Next;
} *LiStack;

bool initListack(LiStack &L) // 不带头节点
{
    L == NULL;
    return true;
}
bool push(LiStack &L, Elemtype c)
{
    LinkNode *p = (LinkNode *)malloc(sizeof(LinkNode));
    if (p == NULL)
    {
        return false; // 内存分配失败
    }
    p->data = c;
    p->Next = L;
    L = p;
    return true;
}
bool display(LiStack L, int n) // n:出栈几个
{
    cout << "出栈" << n << "个数据" << endl;
    for (int i = 0; i < n; ++i)
    {
        if (L == NULL)
        {
            cout << "栈已空,无法出栈!" << endl;
            return false;
        }
        cout << L->data << endl;
        L = L->Next;
    }
    return true;
}
Elemtype pop(LinkNode *L)
{
    if (L == NULL)
    {
        cout << "栈已空,无法出栈!" << endl;
        return false;
    }
    return L->data; // 返回栈顶元素
}

bool duichen(LiStack L, string S)
{
    for (int i = 0; i < S.length() / 2; ++i)
    {
        push(L, S[i]);
    }

    if (S.length() % 2 == 0) // 字符串偶数长
    {
        for (int i = 0; i < S.length() / 2; ++i)
        {
            if (pop(L) != S[S.length() / 2 + i])
            {
                return false;
            }
            L = L->Next;
        }
    }
    else // 字符串奇数长
    {
        for (int i = 0; i < S.length() / 2; ++i)
        {
            if (pop(L) != S[S.length() / 2 + i + 1])
            {
                return false;
            }
            L = L->Next;
        }
    }
    return true;
}
int main()
{
    while (1)
    {

        LiStack L;
        initListack(L);
        cout << "请输入 入栈的字符串:" << endl;
        string S;
        cin >> S;
        // for (int i = 0; i < S.length(); ++i)
        // {
        //     push(L, S[i]);  //测试输出函数
        // }
        // display(L, S.length());
        if (duichen(L, S))
        {
            cout << "对称!" << endl;
        }
        else
        {
            cout << "不对称!" << endl;
        }
    }
    return 0;
}
  • 带头节点
#include <iostream>
#include <stdio.h>
#include <string.h>
#define Elemtype char // 栈的数据类型
using namespace std;

typedef struct LinkNode
{
    Elemtype data;
    struct LinkNode *Next;
} *LiStack;

bool initListack(LiStack &L) // 带头节点
{
    L = (LinkNode *)malloc(sizeof(LinkNode));
    if (L == NULL)
    {
        return false; // 内存分配失败
    }
    L->Next = NULL;
    return true;
}
// 入栈
bool push(LiStack &L, Elemtype c)
{
    if (L == NULL)
    {
        return false;
    }
    LinkNode *p = (LinkNode *)malloc(sizeof(LinkNode));
    if (p == NULL)
    {
        return false; // 内存分配失败
    }
    p->data = c;
    p->Next = L->Next;
    L->Next = p;
    return true;
}
bool display(LiStack L, int n) // n:出栈几个
{
    cout << "出栈" << n << "个数据" << endl;
    for (int i = 0; i < n; ++i)
    {
        if (L == NULL)
        {
            cout << "栈已空,无法出栈!" << endl;
            return false;
        }
        cout << L->Next->data << endl;
        L = L->Next;
    }
    return true;
}
Elemtype pop(LinkNode *L)
{
    if (L == NULL)
    {
        cout << "栈已空,无法出栈!" << endl;
        return false;
    }
    return L->data; // 返回栈顶元素
}

bool duichen(LiStack L, int n)
{
    int i;
    char s[n / 2];              // s字栈
    LinkNode *p = L->Next;      // p是链表的工作指针,指向待处理的当前元素
    for (i = 0; i < n / 2; ++i) // 将链表的前一半入栈
    {
        s[i] = p->data;
        p = p->Next;
    }
    i--;            // 恢复栈顶位置
    if (n % 2 == 1) // 如果是奇数链表,跳过中间结点,指向后一半部分的第一个位置
    {
        p = p->Next;
    }
    while (p != NULL && s[i] == p->data)
    {
        i--;
        p = p->Next;
    }
    if (i == -1)
    {
        return true;
    }
    else
    {
        return false;
    }
}
int main()
{
    while (1)
    {

        LiStack L;
        initListack(L);
        cout << "请输入 入栈的字符串:" << endl;
        string S;
        cin >> S;
        for (int i = 0; i < S.length(); ++i)
        {
            push(L, S[i]);
        }
        // display(L, S.length());// 测试输出函数
        if (duichen(L, S.length()))
        {
            cout << "对称!" << endl;
        }
        else
        {
            cout << "不对称!" << endl;
        }
    }
    return 0;
}
b.栈的应用,括号匹配
  • 核心代码
// 7.括号匹配
bool brcketcheck()
{
    SqStack S;    // 申明栈时就创建地址空间
    InitStake(S); // 初始化
    string s1;
    cout << "请输入括号表达式" << endl;
    cin >> s1;
    for (int i = 0; i < s1.length(); ++i)
    {
        if (s1[i] == '(' || s1[i] == '[' || s1[i] == '{') // 扫描到左括号就入栈
        {
            PushStack(S, s1[i]);
        }
        else if (s1[i] == ')' || s1[i] == '}' || s1[i] == ']') // 扫描到右括号,与栈顶元素进行比较
        {
            if (StackEmpty(S)) // 扫描到右括号。且当前的栈为空
            {
                return false;
            }
            Elemtype topElem;
            PopStack(S, topElem);               // 栈顶元素出栈
            if (s1[i] == ')' && topElem != '(') // 扫描到右括号就与栈顶元素进行比较
            {
                return false;
            }

            if (s1[i] == ']' && topElem != '[')
            {
                return false;
            }

            if (s1[i] == '}' && topElem != '{')
            {
                return false;
            }
        }
    }
    return StackEmpty(S);
}
  • 完整代码
#include <iostream>
#include <stdio.h>
#define MaxSize 50    // 栈的最大容量
#define Elemtype char // 栈的数据类型
using namespace std;

typedef struct
{
    Elemtype data[MaxSize]; // 存放栈中的元素
    int top;                // 记录栈顶指针
} SqStack;

// 1.初始化
void InitStake(SqStack &S)
{
    S.top = -1;
}
// 2.判断栈空
bool StackEmpty(SqStack S)
{
    if (S.top == -1)
    {
        return true;
    }
    else
    {
        return false;
    }
}
// 3.进栈
bool PushStack(SqStack &S, Elemtype x)
{
    if (S.top == MaxSize - 1) // 栈满
    {
        return false;
    }
    S.data[++S.top] = x;
    return true;
}
// 4.出栈
bool PopStack(SqStack &S, Elemtype &x)
{
    if (StackEmpty(S)) // 栈空
    {
        return false;
    }
    x = S.data[S.top--];
    return true;
}
// 5.读取栈顶元素
bool GetStack(SqStack S, Elemtype &x)
{
    if (StackEmpty(S)) // 栈空
    {
        return false;
    }
    x = S.data[S.top];
    return true;
}
// 6.输出栈中的全部元素
void show(SqStack S)
{
    Elemtype x;
    while (PopStack(S, x))
    {
        cout << x << " ";
    }
}
// 7.括号匹配
bool brcketcheck()
{
    SqStack S;    // 申明栈时就创建地址空间
    InitStake(S); // 初始化
    string s1;
    cout << "请输入括号表达式" << endl;
    cin >> s1;
    for (int i = 0; i < s1.length(); ++i)
    {
        if (s1[i] == '(' || s1[i] == '[' || s1[i] == '{') // 扫描到左括号就入栈
        {
            PushStack(S, s1[i]);
        }
        else if (s1[i] == ')' || s1[i] == '}' || s1[i] == ']') // 扫描到右括号,与栈顶元素进行比较
        {
            if (StackEmpty(S)) // 扫描到右括号。且当前的栈为空
            {
                return false;
            }
            Elemtype topElem;
            PopStack(S, topElem);               // 栈顶元素出栈
            if (s1[i] == ')' && topElem != '(') // 扫描到右括号就与栈顶元素进行比较
            {
                return false;
            }

            if (s1[i] == ']' && topElem != '[')
            {
                return false;
            }

            if (s1[i] == '}' && topElem != '{')
            {
                return false;
            }
        }
    }
    return StackEmpty(S);
}
int main()
{
    while (1)
    {
        if (brcketcheck())
        {
            cout << "匹配成功,合法括号序列!" << endl;
        }
        else
        {
            cout << "匹配失败,非法括号序列!" << endl;
        }
    }

    return 0;
}

c.中缀表达式转后缀表达式

C++详细帖子
C动态数组详细帖子
realloc的原理

#include <iostream>
#include <string>
#include <stack>
#include <ctype.h>
using namespace std;
int prio(char op)
{ // 给运算符排序
    if (op == '*' || op == '/')
        return 2;
    if (op == '+' || op == '-')
        return 1;
    if (op == '(')
        return 0;
    return -1;
}
bool trans(string &infix, string &postfix)
{
    stack<char> s;
    for (int i = 0; i < infix.size(); ++i) // 逐个扫描中缀表达式
    {
        if (isdigit(infix[i])) // 数字直接输出
        {
            postfix += infix[i];
        }
        else if (s.empty()) // 栈空直接符号入栈
        {
            s.push(infix[i]);
        }
        else if (infix[i] == '(') //'('直接入栈
        {
            s.push(infix[i]);
        }
        else if (infix[i] == ')') //')'将栈中'('后面入栈的都加入输出字符串
        {
            while (s.top() != '(')
            {
                postfix += s.top();
                s.pop();
            }
            s.pop(); //'栈中'('出栈,不输出'
        }
        else
        {
            if (prio(infix[i]) >= prio(s.top()))
            {
                s.push(infix[i]);
            }
            while (prio(infix[i]) < prio(s.top()))
            {
                postfix += s.top();
                s.pop();
                if (s.empty())
                {
                    break;
                }
            }
        }
    }

    while (!s.empty()) // 扫描结束,将栈中的元素全部输出
    {
        postfix += s.top();
        s.pop();
    }
    return true;
}
int main()
{
    string inpix;
    string postpix;
    cout << "请输入中缀表达式:" << endl;
    cin >> inpix;
    trans(inpix, postpix);
    cout << "后缀表达式为:" << postpix << endl;
    return 0;
}

d.P96: 02
#include <stdio.h>
#include <iostream>
#include <stack>
using namespace std;
#define MAX 10
void train_Arrange(char *train)
{
    stack<char> s1;
    char train1[MAX];
    int j = 0; // 用于存放调度后的火车序列
    for (int i = 0; i < sizeof(train) / sizeof(train[0]); ++i)
    {
        if (train[i] == 'H')
        {
            s1.push(train[i]);
        }
        else
        {
            train1[j++] = train[i];
        }
    }
    while (!s1.empty())
    {
        train1[j++] = s1.top();
        s1.pop();
    }
    printf("%s", train1);
}
int main()
{
    char train[MAX];
    printf("请输入火车的序列(H硬座,S软座):");
    scanf("%s", &train);
    train_Arrange(train);
    return 0;
}
e.栈实现递归函数非递归计算P96:03
#include <iostream>
#define Elemtype int
using namespace std;
typedef struct stack
{
    Elemtype data[2];
    int top;
} stack;
void initSatck(stack &s)
{
    s.top = -1;
}
bool push(stack &s, Elemtype e)
{
    s.data[++s.top] = e;
    return true;
}
bool pop(stack &s, Elemtype &e)
{
    e = s.data[s.top--];
    return true;
}
Elemtype top(stack s)
{
    return s.data[s.top];
}
double p(int n, double x)
{
    // 1.定义个数据栈,并初始化。
    stack s;
    initSatck(s);
    // 2.定义3个变量,进行出栈进栈运算
    int fv1 = 1;
    int fv2 = 2 * x;
    int fv3;
    // 3.将初始n=0和n=1时的变量压入栈
    push(s, fv1);
    push(s, fv2);
    // 开始挨个计算
    for (int i = n; i >= 2; --i)
    {
        // 出栈
        pop(s, fv2);
        pop(s, fv1);
        fv3 = 2 * x * fv2 - 2 * (i - 1) * fv1; // 计算
        // 交换
        fv1 = fv2;
        fv2 = fv3;
        // 压栈
        push(s, fv1);
        push(s, fv2);
    }
    return top(s);
}
int main()
{

    cout << p(3, 1) << endl;
    return 0;
}

2.队列

1.顺序存储循环队列

a. 牺牲一个单元来区分队满和队空

#include <iostream>
#include <stdio.h>
#include <string.h>
#define MaxSize 50
#define Elemtype char // 栈的数据类型
using namespace std;

// 1.顺序循环队列
typedef struct
{
    Elemtype data[MaxSize];
    int front, rear;
} SqQueue;

// 2.初始化
void initQueue(SqQueue &Q)
{
    Q.front = Q.rear = 0;
}
// 3.判空
bool isEmpty(SqQueue Q)
{
    if (Q.rear == Q.front)
    {
        return true;
    }
    return false;
}
// 4.入队
bool EnQueue(SqQueue &Q, Elemtype x)
{
    if ((Q.rear + 1) % MaxSize == Q.front) // 队列满
    {
        return false;
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % MaxSize;
    return true;
}
// 5.出队
bool DeQueue(SqQueue &Q, Elemtype &x)
{
    if (isEmpty(Q))
    {
        return false; // 队列满
    }
    x = Q.data[Q.front];
    Q.front = (Q.front + 1) % MaxSize;
    return true;
}
int main()
{
    SqQueue S;
    initQueue(S);
    EnQueue(S, 'h');
    char X;
    DeQueue(S, X);
    cout << X << endl;
    return 0;
}
b. tag标记来区分队满还是队空

#include <iostream>
#include <stdio.h>
#include <string.h>
#define MaxSize 50
#define Elemtype char // 栈的数据类型
using namespace std;

// 1.顺序循环队列
typedef struct
{
    Elemtype data[MaxSize];
    int front, rear;
    int tag; // tag标记
} SqQueue;

// 2.初始化
void initQueue(SqQueue &Q)
{
    Q.front = Q.rear = 0;
    Q.tag = 0;
}
// 3.判空
bool isEmpty(SqQueue Q)
{
    if (Q.rear == Q.front && Q.tag == 0)
    {
        return true;
    }
    return false;
}
// 4.入队
bool EnQueue(SqQueue &Q, Elemtype x)
{
    if (Q.front == Q.rear && Q.tag == 1) // 队列满
    {
        return false;
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % MaxSize;
    Q.tag = 1;
    return true;
}
// 5.出队
bool DeQueue(SqQueue &Q, Elemtype &x)
{
    if (isEmpty(Q))
    {
        return false; // 队列满
    }
    x = Q.data[Q.front];
    Q.front = (Q.front + 1) % MaxSize;
    Q.tag = 0;
    return true;
}
int main()
{
    SqQueue S;
    initQueue(S);
    EnQueue(S, 'h');
    char X;
    DeQueue(S, X);
    cout << X << endl;
    return 0;
}

2.链式存储

a.单链表链式存储队列

在这里插入图片描述


#include <iostream>
#include <stdio.h>
#include <string.h>
#define MaxSize 50
#define Elemtype char // 栈的数据类型
using namespace std;

// 1.链式队列
typedef struct LinkNode
{
    Elemtype data;
    struct LinkNode *Next;
} LinkNode;
typedef struct LinkQueue
{
    LinkNode *rear;
    LinkNode *front;
} LinkQueue;

// 2.初始化
void initQueue(LinkQueue &Q)//带头节点
{
    Q.rear = Q.front = (LinkNode *)malloc(sizeof(LinkNode));
    Q.rear->Next = NULL;
}
// 3.判空
bool isEmpty(LinkQueue Q)
{
    if (Q.rear == Q.front)
    {
        return true;
    }
    return false;
}
// 4.入队
bool EnQueue(LinkQueue &Q, Elemtype x)
{
    LinkNode *q = (LinkNode *)malloc(sizeof(LinkNode));
    if (q == NULL)
    {
        return false;
    }
    q->data = x;
    q->Next = NULL;
    Q.rear->Next = q;
    Q.rear = q;
    return true;
}
// 5.出队
bool DeQueue(LinkQueue &Q, Elemtype &x)
{
    if (isEmpty(Q))
    {
        return false; // 队列空
    }
    LinkNode *q = Q.front->Next; // 头节点
    x = q->data;
    Q.front->Next = q->Next;
    if (q == Q.rear) // 若原队列中只有一个结点,删除后变空。
    {
        Q.front = Q.rear;
    }
    free(q);
    return true;
}
int main()
{
    LinkQueue Q;
    initQueue(Q);
    EnQueue(Q, 'h');
    Elemtype X;
    DeQueue(Q, X);
    cout << X << endl;
    return 0;
}
b.循环单链表存储队列
  • 2019年真题
    在这里插入图片描述
  • 初始化 和判空

在这里插入图片描述

// 2.初始化
void initQueue(LinkQueue &Q)
{
    Q.rear = Q.front = (LinkNode *)malloc(sizeof(LinkNode));
    Q.rear->Next = Q.front; // 队尾next指针指向队头
}
// 3.判空
bool isEmpty(LinkQueue Q)
{
    if (Q.rear == Q.front)
    {
        cout << "队空!!" << endl;
        return true;
    }
    return false;
}
  • 判满
    在这里插入图片描述
// 4.判满
bool QueueOverflow(LinkQueue Q)
{
    if (Q.rear->Next == Q.front)
    {
        cout << "队满" << endl;
        return true;
    }
    return false;
}
  • 入队
    在这里插入图片描述
    在这里插入图片描述
// 4.入队
bool EnQueue(LinkQueue &Q, Elemtype x)
{
    if (QueueOverflow(Q))
    {
        cout << "队列满,我扩充啦!!" << endl;
        LinkNode *q = (LinkNode *)malloc(sizeof(LinkNode));
        if (q == NULL)
        {
            return false;
        }
        Q.rear->data = x;
        q->Next = Q.rear->Next;
        Q.rear->Next = q;
        Q.rear = q;
    }
    else
    {
        cout << "队未满,直接添加啦!!" << endl;
        Q.rear->data = x;
        Q.rear = Q.rear->Next;
    }
    return true;
}
  • 出队
    在这里插入图片描述
// 5.出队
bool DeQueue(LinkQueue &Q, Elemtype &x)
{
    if (isEmpty(Q))
    {
        return false; // 队列空
    }
    x = Q.front->data;
    Q.front = Q.front->Next;
    return true;
}
  • 完整代码
#include <iostream>
#include <stdio.h>
#include <string.h>
#define Elemtype char // 栈的数据类型
using namespace std;

// 1.循环链式队列
typedef struct LinkNode
{
    Elemtype data;
    struct LinkNode *Next;
} LinkNode;
typedef struct LinkQueue
{
    LinkNode *rear;
    LinkNode *front;
} LinkQueue;

// 2.初始化
void initQueue(LinkQueue &Q)
{
    Q.rear = Q.front = (LinkNode *)malloc(sizeof(LinkNode));
    Q.rear->Next = Q.front; // 队尾next指针指向队头
}
// 3.判空
bool isEmpty(LinkQueue Q)
{
    if (Q.rear == Q.front)
    {
        cout << "队空!!" << endl;
        return true;
    }
    return false;
}
// 4.判满
bool QueueOverflow(LinkQueue Q)
{
    if (Q.rear->Next == Q.front)
    {
        cout << "队满" << endl;
        return true;
    }
    return false;
}
// 4.入队
bool EnQueue(LinkQueue &Q, Elemtype x)
{
    if (QueueOverflow(Q))
    {
        cout << "队列满,我扩充啦!!" << endl;
        LinkNode *q = (LinkNode *)malloc(sizeof(LinkNode));
        if (q == NULL)
        {
            return false;
        }
        Q.rear->data = x;
        q->Next = Q.rear->Next;
        Q.rear->Next = q;
        Q.rear = q;
    }
    else
    {
        cout << "队未满,直接添加啦!!" << endl;
        Q.rear->data = x;
        Q.rear = Q.rear->Next;
    }
    return true;
}
// 5.出队
bool DeQueue(LinkQueue &Q, Elemtype &x)
{
    if (isEmpty(Q))
    {
        return false; // 队列空
    }
    x = Q.front->data;
    Q.front = Q.front->Next;
    return true;
}
int main()
{
    LinkQueue Q;
    initQueue(Q);
    // 先添加4个元素,队列满的需要扩充!
    EnQueue(Q, 'a');
    EnQueue(Q, 'b');
    EnQueue(Q, 'c');
    EnQueue(Q, 'd');
    // 出队一个元素,队有一个空位
    Elemtype X;
    DeQueue(Q, X);
    cout << X << endl;
    // 有一个空位,入队无需扩充!
    EnQueue(Q, 'e');
    // 没有空位了,入队需要扩充!
    EnQueue(Q, 'f');
    return 0;
}

3.练习题

  • Q是一个队列,S是一个空栈,实现将队列中的元素逆置的算法。
说明:代码前一部分是队列的实现,后一部分是栈的实现
#include <iostream>
#include <stdio.h>
#include <string.h>
#define MaxSize 50
#define Elemtype char // 栈的数据类型
using namespace std;
//___________________________________队列
// 1.顺序循环队列
typedef struct
{
    Elemtype data[MaxSize];
    int front, rear;
} SqQueue;

// 2.初始化
void initQueue(SqQueue &Q)
{
    Q.front = Q.rear = 0;
}
// 3.判空
bool isEmpty(SqQueue Q)
{
    if (Q.rear == Q.front)
    {
        return true;
    }
    return false;
}
// 4.入队
bool EnQueue(SqQueue &Q, Elemtype x)
{
    if ((Q.rear + 1) % MaxSize == Q.front) // 队列满
    {
        return false;
    }
    Q.data[Q.rear] = x;
    Q.rear = (Q.rear + 1) % MaxSize;
    return true;
}
// 5.出队
bool DeQueue(SqQueue &Q, Elemtype &x)
{
    if (isEmpty(Q))
    {
        return false; // 队列满
    }
    x = Q.data[Q.front];
    Q.front = (Q.front + 1) % MaxSize;
    return true;
}

//_____________________________________________________栈
typedef struct SqStack
{
    Elemtype data[MaxSize]; // 存放栈中的元素
    int top;                // 记录栈顶指针
} SqStack;

// 1.初始化
void InitStake(SqStack &S)
{
    S.top = -1;
}
// 2.判断栈空
bool StackEmpty(SqStack S)
{
    if (S.top == -1)
    {
        return true;
    }
    else
    {
        return false;
    }
}
// 3.进栈
bool PushStack(SqStack &S, Elemtype x)
{
    if (S.top == MaxSize - 1) // 栈满
    {
        return false;
    }
    S.data[++S.top] = x;
    return true;
}
// 4.出栈
bool PopStack(SqStack &S, Elemtype &x)
{
    if (StackEmpty(S)) // 栈空
    {
        return false;
    }
    x = S.data[S.top--];
    return true;
}
// 5.读取栈顶元素
bool GetStack(SqStack S, Elemtype &x)
{
    if (StackEmpty(S)) // 栈空
    {
        return false;
    }
    x = S.data[S.top];
    return true;
}

// 将队列中的元素逆转
bool Inverser(SqStack &S, SqQueue &Q)
{
    Elemtype x;
    while (!isEmpty(Q)) // 将队列的元素压入栈中
    {
        DeQueue(Q, x);
        PushStack(S, x);
    }
    while (!StackEmpty(S)) // 将栈中的元素逆置压入队列中
    {
        PopStack(S, x);
        EnQueue(Q, x);
    }
    return true;
}
void test()
{
    SqQueue Q;
    initQueue(Q);
    SqStack S;
    InitStake(S);
    // 向队列中添加a-j 10个元素
    for (int i = 0; i < 10; ++i)
    {
        EnQueue(Q, char(i + 97));
    }
    Inverser(S, Q); // 实现队列中的元素逆转
    Elemtype X;
    while (!isEmpty(Q))
    {
        DeQueue(Q, X);
        cout << X << " ";
    }
}
int main()
{
    test();
    return 0;
}
b.p96: 04客车货车上船问题
  • 核心代码
void k(SqQueue &q1, SqQueue &q2, SqQueue &q3) // 客车上船
{
    Elemtype x;
    if (!isEmpty(q1)) // 客车有
    {
        Dequeue(q1, x);
        Enqueue(q3, x);
    }
    else if (!isEmpty(q2)) // 客车无,货车代替
    {
        Dequeue(q2, x);
        Enqueue(q3, x);
    }
}
void h(SqQueue &q1, SqQueue &q2, SqQueue &q3) // 货车上船
{
    Elemtype x;
    if (!isEmpty(q2)) // 货车有
    {
        Dequeue(q2, x);
        Enqueue(q3, x);
    }
    else if (!isEmpty(q1)) // 货车无,客车代替
    {
        Dequeue(q1, x);
        Enqueue(q3, x);
    }
}
void manger(SqQueue &q1, SqQueue &q2, SqQueue &q3)
{
    for (int j = 0; j < 2; ++j) // 4客车1货车循环次数
    {
        for (int i = 1; i <= 4; ++i)
        {
            k(q1, q2, q3); // 客车上船
        }
        h(q1, q2, q3); // 货车上船
    }
}
  • 完整代码
#include <iostream>
#define MaxSize 11 // 留出一个空结点,用来区分队满和队空
#define Elemtype char
using namespace std;
typedef struct SqQueue
{
    Elemtype data[MaxSize];
    int front;
    int rear;
} SqQueue;
bool initSqQueue(SqQueue &q)
{
    q.front = q.rear = 0;
    return true;
}
bool isEmpty(SqQueue q)
{
    if (q.front == q.rear)
    {
        return true;
    }
    else
    {
        return false;
    }
}
bool Enqueue(SqQueue &q, Elemtype x)
{
    if ((q.rear + 1) % MaxSize == q.front) // 队满
    {
        return false;
    }
    q.data[q.rear] = x;
    q.rear = (q.rear + 1) % MaxSize;
    return true;
}
bool Dequeue(SqQueue &q, Elemtype &x)
{
    if (q.front == q.rear) // 栈空
    {
        return false;
    }
    x = q.data[q.front];
    q.front = (q.front + 1) % MaxSize;
    return true;
}
void k(SqQueue &q1, SqQueue &q2, SqQueue &q3) // 客车上船
{
    Elemtype x;
    if (!isEmpty(q1)) // 客车有
    {
        Dequeue(q1, x);
        Enqueue(q3, x);
    }
    else if (!isEmpty(q2)) // 客车无,货车代替
    {
        Dequeue(q2, x);
        Enqueue(q3, x);
    }
}
void h(SqQueue &q1, SqQueue &q2, SqQueue &q3) // 货车上船
{
    Elemtype x;
    if (!isEmpty(q2)) // 货车有
    {
        Dequeue(q2, x);
        Enqueue(q3, x);
    }
    else if (!isEmpty(q1)) // 货车无,客车代替
    {
        Dequeue(q1, x);
        Enqueue(q3, x);
    }
}
void manger(SqQueue &q1, SqQueue &q2, SqQueue &q3)
{
    for (int j = 0; j < 2; ++j) // 4客车1货车循环次数
    {
        for (int i = 1; i <= 4; ++i)
        {
            k(q1, q2, q3); // 客车上船
        }
        h(q1, q2, q3); // 货车上船
    }
}
void show(SqQueue q) // 输出函数
{
    Elemtype x;
    while (!isEmpty(q))
    {
        Dequeue(q, x);
        cout << x << " ";
    }
    cout << endl;
}
int main()
{
    SqQueue q1; // 客车
    SqQueue q2; // 货车
    SqQueue q3; // 运输船
    initSqQueue(q1);
    initSqQueue(q2);
    initSqQueue(q3);
    int n1, n2 = 0;
    cout << "请输入客车数量:" << endl;
    cin >> n1;
    cout << "请输入货车数量:" << endl;
    cin >> n2;
    // 客车进队
    for (int i = 0; i < n1; ++i)
    {
        Enqueue(q1, 'k');
    }
    // 货车进队
    for (int i = 0; i < n2; ++i)
    {
        Enqueue(q2, 'h');
    }
    manger(q1, q2, q3); // 上船
    show(q3);
    return 0;
}

3.数组与特殊矩阵

(1).稀疏矩阵

<1>. 顺序存储三元组

在这里插入图片描述

#include <stdio.h>
#define MaxSize 4
#define Elemtype int
// 存储三元组的结构体
typedef struct triple
{
    int i, j;      // 存放数组的行纵坐标
    Elemtype data; // 存放数组数据
} triple;
// 存储稀疏矩阵的结构体
typedef struct TSMatrix
{
    triple data[MaxSize];
    int mu, nu, tu; // mu和nu分别记录矩阵的行数和列数,tu记录矩阵中所有的非0元素的个数
} TSMatrix;
// 实例化稀疏矩阵T
bool push(TSMatrix &t)
{
    printf("请分别输入稀疏矩阵中非零数:\n");
    scanf("%d", &t.tu);
    for (int k = 0; k < t.tu; ++k)
    {
        printf("请输入第%d个数的行坐标:", k + 1);
        scanf("%d", &t.data[k].i);
        printf("请输入第%d个数的纵坐标:", k + 1);
        scanf("%d", &t.data[k].j);
        printf("请输入第%d个数的值:", k + 1);
        scanf("%d", &t.data[k].data);
    }
    return true;
}
// 稀疏矩阵输出函数
void display(TSMatrix t)
{
    for (int i = 1; i <= t.mu; ++i) // 行
    {
        for (int j = 1; j <= t.nu; ++j) // 列
        {
            bool flag = false; // 标记
            for (int k = 0; k < t.tu; ++k)
            {
                if (i == t.data[k].i && j == t.data[k].j)
                {
                    printf("%d", t.data[k].data);
                    printf(" ");
                    flag = true;
                    break;
                }
            }
            if (!flag)
            {
                printf("%d", 0);
                printf(" ");
            }
        }
        printf("\n");
    }
}
int main()
{
    TSMatrix t;
    t.mu = t.nu = 3;
    push(t);
    display(t);
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值