第二章(链表)
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.中缀表达式转后缀表达式
#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;
}