## 实验1
### 8576 顺序线性表的基本操作
```cpp
#include<stdio.h>
#include<malloc.h>
#define OK 1
#define ERROR 0
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define ElemType int
typedef struct
{
int *elem;
int length;
int listsize;
}SqList;
int InitList_Sq(SqList &L)
{
// 算法2.3,构造一个空的线性表L,该线性表预定义大小为LIST_INIT_SIZE
// 请补全代码
L.elem = (int*)malloc(LIST_INIT_SIZE*sizeof(int));
if(!L.elem) return ERROR;
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return OK;
}
int Load_Sq(SqList &L)
{
// 输出顺序表中的所有元素
int i;
if(!L.length) printf("The List is empty!"); // 请填空
else
{
printf("The List is: ");
for(int i=0;i<L.length;i++) printf("%d ",L.elem[i]); // 请填空
}
printf("\n");
return OK;
}
int ListInsert_Sq(SqList &L,int i,int e)
{
// 算法2.4,在顺序线性表L中第i个位置之前插入新的元素e
// i的合法值为1≤i≤L.length +1
// 请补全代码
if(i<1 || i>L.length+1) return ERROR;
if(L.length+1>LIST_INIT_SIZE){
int* newbase = (int*)realloc(L.elem,sizeof(int)*(L.listsize+LISTINCREMENT));//用于判断是否能分配成功
if(!newbase) return ERROR;;
L.elem = newbase;
L.listsize += LISTINCREMENT;
}
int *q = &(L.elem[i-1]);
for(int *p = &(L.elem[L.length-1]);p>=q;p--){
*(p+1) = *p;
}
++L.length;
*q = e;
return OK;
}
int ListDelete_Sq(SqList &L,int i, int &e)
{
// 算法2.5,在顺序线性表L中删除第i个位置的元素,并用e返回其值
// i的合法值为1≤i≤L.length
// 请补全代码
if(i<1 || i>L.length){
return ERROR;
}
int *q = &(L.elem[i-1]);
e = *q;
for(int* p = &(L.elem[L.length-1]);q<p;q++){
*(q) = *(q+1);
}
--L.length;
return e;
}
int main()
{
SqList T;
int a, i;
ElemType e, x;
if(InitList_Sq(T)) // 判断顺序表是否创建成功
{
printf("A Sequence List Has Created.\n");
}
while(1)
{
printf("1:Insert element\n2:Delete element\n3:Load all elements\n0:Exit\nPlease choose:\n");
scanf("%d",&a);
switch(a)
{
case 1: scanf("%d%d",&i,&x);
if(!ListInsert_Sq(T,i,x)) printf("Insert Error!\n"); // 执行插入函数,根据返回值判断i值是否合法
else printf("The Element %d is Successfully Inserted!\n", x);
break;
case 2: scanf("%d",&i);
if(!ListDelete_Sq(T,i,e)) printf("Delete Error!\n"); // 执行删除函数,根据返回值判断i值是否合法
else printf("The Element %d is Successfully Deleted!\n", e);
break;
case 3: Load_Sq(T);
break;
case 0: return 1;
}
}
}
```
### 8579 链式线性表的基本操作
```cpp
#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define ElemType int
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
int CreateLink_L(LinkList &L,int n){
// 创建含有n个元素的单链表
LinkList p,q;
int i;
ElemType e;
L = new LNode;
L->next = NULL; // 先建立一个带头结点的单链表
q = L;
for (i=0; i<n; i++) {
scanf("%d", &e);
p = new LNode; // 生成新结点
p->data = e;
q->next = p;
q = p;
}
return OK;
}
int LoadLink_L(LinkList &L){
// 单链表遍历
LinkList p = L->next;
if(p==NULL)printf("The List is empty!"); // 请填空
else
{
printf("The LinkList is:");
while(p!=NULL) // 请填空
{
printf("%d ",p->data);
p = p->next;
}
}
printf("\n");
return OK;
}
int LinkInsert_L(LinkList &L,int i,ElemType e){
// 算法2.9
// 在带头结点的单链线性表L中第i个位置之前插入元素e
LinkList p = L;
int j = 0;
while(p!=NULL && j<i-1){
p = p->next;
j++;
}
if(p==NULL || j>i-1) return ERROR;
LinkList s = new LNode;
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
int LinkDelete_L(LinkList &L,int i, ElemType &e){
// 算法2.10
// 在带头结点的单链线性表L中,删除第i个元素,并用e返回其值
LinkList p = L;
int j = 0;
while(p->next!=NULL && j<i-1){
p = p->next;
j++;
}
if(p->next==NULL || j>i-1) return ERROR;
LinkList q = p->next;
e = q->data;
p->next = q->next;
delete q;
return OK;
}
int main()
{
LinkList T;
int a,n,i;
ElemType x, e;
printf("Please input the init size of the linklist:\n");
scanf("%d",&n);
printf("Please input the %d element of the linklist:\n", n);
if(CreateLink_L(T,n))
{
printf("A Link List Has Created.\n");
LoadLink_L(T);
}
while(1)
{
printf("1:Insert element\n2:Delete element\n3:Load all elements\n0:Exit\nPlease choose:\n");
scanf("%d",&a);
switch(a)
{
case 1: scanf("%d%d",&i,&x);
if(LinkInsert_L(T,i,x)) printf("The Element %d is Successfully Inserted!\n", x);
else printf("Insert Error!\n");
break;
case 2: scanf("%d",&i);
if(LinkDelete_L(T,i,e)) printf("The Element %d is Successfully Deleted!\n", e);
else printf("Delete Error!\n");
break;
case 3: LoadLink_L(T);
break;
case 0: return 1;
}
}
}
```
### 8580 合并链表
```cpp
#include<stdio.h>
#include<malloc.h>
#define ERROR 0
#define OK 1
#define ElemType int
typedef int Status;
typedef struct LNode
{
int data;
struct LNode *next;
}LNode,*LinkList;
Status InitList_L(LinkList &L) {
// 操作结果:构造一个空的线性表L
L = (LinkList)malloc(sizeof(LNode)); // 产生头结点
if (!L) return ERROR; // 存储分配失败
L->next = NULL; // 指针域为空
return OK;
} // InitList_L
void PrintList_L(LinkList L) {
// 输出单链线性表L的所有元素值
LinkList p = L->next;
while (p) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
} // PrintList_L
Status ListInsert_L(LinkList &L, int i, ElemType e) { // 算法2.9
// 在带头结点的单链线性表L的第i个元素之前插入元素e
LinkList p,s;
p = L;
int j = 0;
while (p && j < i-1) { // 寻找第i-1个结点
p = p->next;
++j;
}
if (!p || j > i-1) return ERROR; // i小于1或者大于表长
s = (LinkList)malloc(sizeof(LNode)); // 生成新结点
s->data = e; s->next = p->next; // 插入L中
p->next = s;
return OK;
} // LinstInsert_L
Status ListDelete_L(LinkList &L, int i, ElemType &e) { // 算法2.10
// 在带头结点的单链线性表L中,删除第i个元素,并由e返回其值
LinkList p,q;
p = L;
int j = 0;
while (p->next && j < i-1) { // 寻找第i个结点,并令p指向其前趋
p = p->next;
++j;
}
if (!(p->next) || j > i-1) return ERROR; // 删除位置不合理
q = p->next;
p->next = q->next; // 删除并释放结点
e = q->data;
free(q);
return OK;
} // ListDelete_L
void MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc) {
// 已知单链线性表La和Lb的元素按值非递减排列。
// 归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列。
LinkList pa = La->next, pb = Lb->next, pc;
Lc = pc = La; // 用La的头结点作为Lc的头结点
while (pa && pb) {
if (pa->data <= pb->data) {
pc->next = pa;
pc = pa;
pa = pa->next;
} else {
pc->next = pb;
pc = pb;
pb = pb->next;
}
}
pc->next = pa ? pa : pb; // 插入剩余段
free(Lb); // 释放Lb的头结点
} // MergeList_L
int main() {
LinkList La, Lb, Lc;
int m, n;
scanf("%d", &m);
InitList_L(La);
for (int i = 1; i <= m; ++i) {
int x;
scanf("%d", &x);
ListInsert_L(La, i, x);
}
scanf("%d", &n);
InitList_L(Lb);
for (int i = 1; i <= n; ++i) {
int x;
scanf("%d", &x);
ListInsert_L(Lb, i, x);
}
printf("List A:");
PrintList_L(La);
printf("List B:");
PrintList_L(Lb);
MergeList_L(La, Lb, Lc);
printf("List C:");
PrintList_L(Lc);
return 0;
} // main
```
### 19080 反转链表
```cpp
nex = cur->next;
cur->next = pre;
pre = cur;
cur = nex;
```
## 实验2
### 8583 顺序栈的基本操作
```cpp
#include<malloc.h>
#include<stdio.h>
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量
typedef int SElemType; // 定义栈元素类型
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
struct SqStack
{
SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
SElemType *top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈
Status InitStack(SqStack &S)
{
S.base = new int[STACK_INIT_SIZE];
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack &S,SElemType e)
{
if(S.top - S.base == S.stacksize){
return ERROR;
}//斩满,无法进栈
else{
*S.top = e;
S.top++;
}
return OK;
}
Status Pop(SqStack &S,SElemType &e)
{
// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
// 请补全代码
if(S.top == S.base){
return ERROR;
}
S.top--;
e = *S.top;
return OK;
}
Status GetTop(SqStack S,SElemType &e)
{
// 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
// 请补全代码
if(S.top == S.base){
return ERROR;
}else{
e = *(--S.top);
}
return OK;
}
int StackLength(SqStack S)
{
// 返回栈S的元素个数
// 请补全代码
if(S.top == S.base){
return 0;
}else{
return S.top- S.base;
}
}
Status StackTraverse(SqStack S)
{
// 从栈顶到栈底依次输出栈中的每个元素
SElemType *p = S.top ; //请填空
if(S.top == S.base)printf("The Stack is Empty!"); //请填空
else
{
printf("The Stack is: ");
while(p--) //请填空
{
if(p==S.base){
printf("%d ", *p);
break;
}
//请填空
printf("%d ", *p);
}
}
printf("\n");
return OK;
}
int main()
{
int a;
SqStack S;
SElemType x, e;
if(InitStack(S)) // 判断顺序表是否创建成功,请填空
{
printf("A Stack Has Created.\n");
}
while(1)
{
printf("1:Push \n2:Pop \n3:Get the Top \n4:Return the Length of the Stack\n5:Load the Stack\n0:Exit\nPlease choose:\n");
scanf("%d",&a);
switch(a)
{
case 1: scanf("%d", &x);
if(!Push(S,x)) printf("Push Error!\n"); // 判断Push是否合法,请填空
else printf("The Element %d is Successfully Pushed!\n", x);
break;
case 2: if(!Pop(S,e)) printf("Pop Error!\n"); // 判断Pop是否合法,请填空
else printf("The Element %d is Successfully Poped!\n", e);
break;
case 3: if(!GetTop(S,e))printf("Get Top Error!\n"); // 判断Get Top是否合法,请填空
else printf("The Top Element is %d!\n", e);
break;
case 4: printf("The Length of the Stack is %d!\n",S.top - S.base); //请填空
break;
case 5:
StackTraverse(S);//请填空
break;
case 0: return 1;
}
}
}
```
### 8584 循环队列的基本操作
```cpp
#include<malloc.h>
#include<stdio.h>
#define OK 1
#define ERROR 0
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int QElemType;
#define MAXQSIZE 100 // 最大队列长度(对于循环队列,最大队列长度要减1)
typedef struct
{
QElemType *base; // 初始化的动态分配存储空间
int front; // 头指针,若队列不空,指向队列头元素
int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
}SqQueue;
Status InitQueue(SqQueue &Q)
{
// 构造一个空队列Q,该队列预定义大小为MAXQSIZE
// 请补全代码
Q.base = new int[MAXQSIZE];
if(Q.base == NULL){
return ERROR;
}
Q.front =Q.rear =0;
return true;
}
Status EnQueue(SqQueue &Q,QElemType e)
{
// 插入元素e为Q的新的队尾元素
// 请补全代码
if((Q.rear+1)%MAXQSIZE!= Q.front){
Q.base[Q.rear] = e;
Q.rear = (Q.rear+1)%MAXQSIZE;
return OK;
}else{
return ERROR;
}
}
Status DeQueue(SqQueue &Q, QElemType &e)
{
// 若队列不空, 则删除Q的队头元素, 用e返回其值, 并返回OK; 否则返回ERROR
// 请补全代码
if(Q.front == Q.rear){
return ERROR;
}else{
e = Q.base[Q.front] ;
Q.front = (Q.front + 1)%MAXQSIZE;
return OK;
}
}
Status GetHead(SqQueue Q, QElemType &e)
{
// 若队列不空,则用e返回队头元素,并返回OK,否则返回ERROR
// 请补全代码
if(Q.front == Q.rear){
return false;
}else{
e = Q.base[Q.front];
return OK;
}
}
int QueueLength(SqQueue Q)
{
// 返回Q的元素个数
// 请补全代码
return (Q.rear - Q.front +MAXQSIZE)%MAXQSIZE;
}
Status QueueTraverse(SqQueue Q)
{
// 若队列不空,则从队头到队尾依次输出各个队列元素,并返回OK;否则返回ERROR.
int i;
i=Q.front;
if(Q.front == Q.rear){
printf("The Queue is Empty!");
return ERROR;
}else{
printf("The Queue is: ");
while(i!=Q.rear) //请填空
{
printf("%d ",Q.base[i] ); //请填空
i = i+1; //请填空
}
}
printf("\n");
return OK;
}
int main()
{
int a;
SqQueue S;
QElemType x, e;
if(InitQueue(S)) // 判断顺序表是否创建成功,请填空
{
printf("A Queue Has Created.\n");
}
while(1)
{
printf("1:Enter \n2:Delete \n3:Get the Front \n4:Return the Length of the Queue\n5:Load the Queue\n0:Exit\nPlease choose:\n");
scanf("%d",&a);
switch(a)
{
case 1: scanf("%d", &x);
if(!EnQueue(S,x)) printf("Enter Error!\n"); // 判断入队是否合法,请填空
else printf("The Element %d is Successfully Entered!\n", x);
break;
case 2: if(!DeQueue(S,e)) printf("Delete Error!\n"); // 判断出队是否合法,请填空
else printf("The Element %d is Successfully Deleted!\n", e);
break;
case 3: if(!GetHead(S,e))printf("Get Head Error!\n"); // 判断Get Head是否合法,请填空
else printf("The Head of the Queue is %d!\n", e);
break;
case 4: printf("The Length of the Queue is %d!\n",QueueLength(S)); //请填空
break;
case 5: QueueTraverse(S); //请填空
break;
case 0: return 1;
}
}
}
```
### 8585 栈的应用——进制转换
```cpp
#include<iostream>
#include<stack>
using namespace std;
int main(){
stack<int> s;
int n;
cin>>n;
if(n==0) s.push(0);
while(n){
s.push(n%8);
n/=8;
}
while(!s.empty()){
cout<<s.top();
s.pop();
}
return 0;
}
```
### 8586 括号匹配检验
```cpp
typedef char SElemType;
#include"malloc.h"
#include"stdio.h"
#include"math.h"
#include"stdlib.h" // exit()
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
#define STACK_INIT_SIZE 10 // 存储空间初始分配量
#define STACKINCREMENT 2 // 存储空间分配增量
struct SqStack
{
SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
SElemType *top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈
Status InitStack(SqStack &S)
{
S.base = new char[STACK_INIT_SIZE];
if(!S.base) return ERROR;
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
Status StackEmpty(SqStack S)
{
if(S.top == S.base)
return TRUE;
return FALSE;
}
Status Push(SqStack &S,SElemType e)
{
if(S.top -S.base ==S.stacksize) return ERROR;
*S.top = e;
S.top++;
return OK;
}
Status Pop(SqStack &S,SElemType &e)
{
if(S.top == S.base) return ERROR;
S.top--;
e = *S.top;
return OK;
}
void check()
{ // 对于输入的任意一个字符串,检验括号是否配对
SqStack s;
SElemType ch[80],*p,e;
if(InitStack(s)) // 初始化栈成功
{
//printf("请输入表达式\n");
scanf("%s",ch);
p=ch;
while(*p) // 没到串尾
switch(*p)
{
case '(':
case '[':Push(s ,*p++);
break; // 左括号入栈,且p++
case ')':
case ']':if(!StackEmpty(s)) // 栈不空
{
Pop(s,e); // 弹出栈顶元素
if(((*p==')')&&(e!='('))||((*p==']')&&(e!='[')))
// 弹出的栈顶元素与*p不配对
{
printf("isn't matched pairs\n");
exit(0);
}
else
{
p++;
break; // 跳出switch语句
}
}
else // 栈空
{
printf("lack of left parenthesis\n");
exit(ERROR);
}
default: p++; // 其它字符不处理,指针向后移
}
if(StackEmpty(s)) // 字符串结束时栈空
printf("matching\n");
else
printf("lack of right parenthesis\n");
}
}
int main()
{
check();
}
```
### 8587 行编辑程序
```cpp
#include<string>//行编辑程序
#include<stack>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
const int N = 10005;
int main()
{
char ch;
int n;
cin >> n;
ch = getchar();//读入第一个字符,换行符
for (int i = 1; i <= n; i++)
{
vector<char>s;//使用vecotor模板,可当作栈
ch = getchar();
while (ch != '\n')
{
switch (ch)
{
case '#':
if (!s.empty())
{
s.pop_back();
}
break; //末尾字符退栈
case '@':
s.clear();
break; //清空栈
default:
s.push_back(ch); //有效字符进栈
}
ch = getchar(); //接收下一个字符
}
for (int i = 0; i < s.size(); i++)//输出
{
cout << s[i];
}
cout << endl;
}
return 0;
}
typedef char SElemType;
#include"malloc.h"
#include"stdio.h"
#include"math.h"
#include"stdlib.h" // exit()
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
#define STACK_INIT_SIZE 10 // 存储空间初始分配量
#define STACKINCREMENT 2 // 存储空间分配增量
struct SqStack
{
SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
SElemType *top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈
Status InitStack(SqStack &S)
{ // 构造一个空栈S
S.base = S.top = new SElemType[STACK_INIT_SIZE];
if(!S.base) return ERROR;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
Status StackEmpty(SqStack S)
{ // 若栈S为空栈,则返回TRUE,否则返回FALSE
if(S.base == S.top) return TRUE;
return FALSE;
}
Status ClearStack(SqStack &S)
{ // 把S置为空栈
S.top=S.base;
return OK;
}
Status DestroyStack(SqStack &S)
{ // 销毁栈S,S不再存在
free(S.base);
S.base=NULL;
S.top=NULL;
S.stacksize=0;
return OK;
}
Status Push(SqStack &S,SElemType e)
{ // 插入元素e为新的栈顶元素
*S.top = e;
S.top++;
return OK;
}
Status Pop(SqStack &S,SElemType &e)
{ // 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
if(S.top == S.base) return ERROR;
S.top--;
e = *S.top;
return OK;
}
Status StackTraverse(SqStack S,Status(*visit)(SElemType))
{ // 从栈底到栈顶依次对栈中每个元素调用函数visit()。
// 一旦visit()失败,则操作失败
while(S.top>S.base)
visit(*S.base++);
printf("\n");
return OK;
}
Status visit(SElemType c)
{
printf("%c",c);
return OK;
}
void LineEdit()
{ // 利用字符栈s,从终端接收一行并送至调用过程的数据区。算法3.2
SqStack s;
char ch,c;
int n,i;
InitStack(s);
scanf("%d",&n);
ch=getchar();
for(i=1;i<=n;i++)
{ ch=getchar();
while(ch!='\n')
{
switch(ch)
{
case '#':Pop(s,c);
break; // 仅当栈非空时退栈
case '@':ClearStack(s);
break; // 重置s为空栈
default :Push(s,ch); // 有效字符进栈
}
ch = getchar(); // 从终端接收下一个字符
}
StackTraverse(s,visit); // 将从栈底到栈顶的栈内字符输出
ClearStack(s); // 重置s为空栈
}
DestroyStack(s);
}
int main()
{
LineEdit();
return 0;
}
```
### 8588 表达式求值
```cpp
#include<cstdlib>
#include<cstdio>
#include <iostream>
#include <cstring>
#define OK 1
#define ERROR 0
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量
typedef int SElemType; // 定义栈元素类型
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
using namespace std;
struct SqStack
{
SElemType *base; // 在栈构造之前和销毁之后,base的值为NULL
SElemType *top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
}; // 顺序栈
Status InitStack(SqStack &S)
{
// 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE
S.base=(SElemType*)malloc(STACK_INIT_SIZE*sizeof(SElemType));
if(!S.base) return ERROR;
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack &S,SElemType e)
{
// 在栈S中插入元素e为新的栈顶元素
if(S.top-S.base>=S.stacksize)
{
S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
if(!S.base) return ERROR;
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
return OK;
}
Status Pop(SqStack &S,SElemType &e)
{
// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
if(S.top==S.base) return ERROR;
e=*--S.top;
return OK;
}
Status GetTop(SqStack S,SElemType &e)
{
// 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
if(S.top==S.base) return ERROR;
e=*(S.top-1);
return OK;
}
int StackLength(SqStack S)
{
// 返回栈S的元素个数
int i;
i=S.top-S.base;
return i;
}
Status StackTraverse(SqStack S)
{
// 从栈顶到栈底依次输出栈中的每个元素
SElemType *p = (SElemType *)malloc(sizeof(SElemType));
p = S.top;
if(S.top==S.base)printf("The Stack is Empty!");
else
{
printf("The Stack is: ");
p--;
while(p>=S.base)
{
printf("%d ", *p);
p--;
}
}
printf("\n");
return OK;
}
char prio(char e,char c){//比较运算符优先级
char n;
switch(c){
case'+':
case'-':{
if(e=='('||e=='=') n='<'; //c>e
else n='>';}break;
case'*':
case'/':{
if(e=='*'||e=='/'||e==')') n='>';//c<e
else n='<';}break;
case'(':{
if(e==')')
{
printf("括号不匹配\n");
exit(ERROR);
}
else n='<';} //c>e;
break;
case')':{
if(e=='(') n='=';
else if(e=='=') {printf("缺少左括号\n");exit(ERROR);}
else n='>';
}//e>c
break;
case'=':{
if(e=='=') n='=';
else if(e=='(') {printf("缺少右括号\n");exit(ERROR);}
else n='>';
} //e>c
}//switch
return n;
}
int main()
{
SqStack s1,s2;//s1操作数栈,s2算符栈
InitStack(s1);
InitStack(s2);
Push(s2,'=');
char w;
w=getchar();
int e;
GetTop(s2,e);
while(w!='='||e!='=')
{
// cout<<w<<endl;
int d=0;
if(w>='0'&&w<='9') {
while (w >= '0' && w <= '9') {
d = d * 10 + (w - '0');
w = getchar();
}
Push(s1, d);
// cout << d << endl;
}
else {
if (prio(e, w) == '<') {
//cout<<"123"<<endl;
Push(s2, w);
//StackTraverse(s1);
w = getchar();
} else if (prio(e, w) == '=' && w == ')') {
//cout<<"321"<<endl;
int t;
Pop(s2, t);
w = getchar();
} else if (prio(e, w) == '>') {
int a, b, c = 0, d;
Pop(s1, a);
Pop(s1, b);
Pop(s2, d);
if (d == '+')
c = a + b;
else if (d == '-')
c = b - a;
else if (d == '/')
c = b / a;
else if (d == '*')
c = b * a;
Push(s1, c);
}
}
GetTop(s2,e);
}
int r;
Pop(s1,r);
cout<<r<<endl;
return 0;
}
```
### 18938 汉诺塔问题
```cpp
#include <iostream>
#include <algorithm>
#include <set>
#include <cmath>
#include <cstring>
#include <map>
using namespace std;
int num;
char a,b,c;
void move(int n,char a,char b){
printf("%c->%d->%c\n", a, n, b);
}
void hanoi(int n,char a,char b,char c){
if(n == 1) {
printf("%c->%d->%c\n", a, n ,c);
return;
}else{
hanoi(n-1,a,c,b);
move(n,a,c);
hanoi(n-1,b,a,c);
}
}
int main(){
cin>>num;
cin>>a>>b>>c;
hanoi(num,a,c,b);
return 0;
}
```
### 8590 队列的应用——银行客户平均等待时间
```cpp
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 10000;
int T,timing,k;
int a[N][N];
double average,sum;
int main(){
cin>>T;
cin>>a[k][0]>>a[k][1];
timing = a[k][0]+a[k++][1];
T--;
while(T--){
cin>>a[k][0]>>a[k][1];
if(a[k][0] <= timing){
sum += timing - a[k][0];
timing += a[k][1];
}else{
timing = (a[k][0]+a[k][1]);
}
k++;
}
average = sum/(k);
printf("%.2f",average);
return 0;
}
```
### 18937 阿克曼(Ackmann)函数
```cpp
#include <iostream>
#include <algorithm>
using namespace std;
int akm(int a,int b){
if(!a) {
return b+1;
}else if((!b)&&a>0){
return akm(a-1,1);
}else if(a>0&&b>0) {
return akm(a-1,akm(a,b-1));
}
}
int main(){
int a,b;
cin>>a>>b;
cout<<akm(a,b)<<endl;
return 0;
}
```
## 实验3
### 8591 计算next值
```cpp
#include "stdio.h"
#include "stdlib.h"
#include "iostream"
#define MAXSTRLEN 255 // 用户可在255以内定义最大串长
typedef unsigned char SString[MAXSTRLEN+1]; // 0号单元存放串的长度
void get_next(SString T,int next[]){
// 算法4.7
// 求模式串T的next函数值并存入数组next
// 请补全代码
int i=1,j=0;next[1]=0;
while(i<=T[0]) {
if(j==0||T[i]==T[j]) {next[++i]=++j;}
else j=next[j];
}
}
int main(){
int next[MAXSTRLEN];
SString S;
int n,i,j;
char ch;
scanf("%d",&n); // 指定要验证NEXT值的字符串个数
ch=getchar();
for(i=1;i<=n;i++)
{
ch=getchar();
for(j=1;j<=MAXSTRLEN&&(ch!='\n');j++) // 录入字符串
{
S[j]=ch;
ch=getchar();
}
S[0]=j-1; // S[0]用于存储字符串中字符个数
get_next(S,next);
printf("NEXT J is:");
for(j=1;j<=S[0];j++)
printf("%d",next[j]);
printf("\n");
}
return 0;
}
```
### 8592 KMP算法
```cpp
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASLBLE -1
#define OVERFLOW -2
#define MAXSTRLEN 255 //用户可在255以内定义最大串长
typedef unsigned char SString[MAXSTRLEN+1]; //0号单元存放串的长度
void get_next(SString T,int next[]){
// 算法4.7
// 求模式串T的next函数值并存入数组next
// 请补全代码
next[1] = 0;
int i=1,j=0;
while(i < T[0]){
if(j==0 || T[i]==T[j]){
i++;
j++;
next[i] = j;
}else{
j = next[j];
}
}
}
int Index_KMP(SString S,SString T,int pos){
// 算法4.6
// 利用模式串T的next函数求T在主串S中第pos个字符之后的位置
// KMP算法。请补全代码
int next[MAXSTRLEN+1],i=0,j=0;
get_next(T,next);
while(i<=S[0]&&j<=T[0]){
if(j==0 || S[i]==T[j]){
i++;
j++;
}else{
j = next[j];
}
}
if(j>=T[0])
return i-T[0];
else
return 0;
}
int main()
{
SString T,S;
int i,j,n;
char ch;
int pos;
scanf(" %d", &n); // 指定n对需进行模式匹配的字符串
ch=getchar();
for(j=1;j<=n;j++)
{
ch=getchar();
for( i=1;i<=MAXSTRLEN&&(ch!='\n');i++) // 录入主串
{
S[i]=ch;
ch=getchar();
}
S[0]=i-1; // S[0]用于存储主串中字符个数
ch=getchar();
for( i=1;i<=MAXSTRLEN&&(ch!='\n');i++) // 录入模式串
{
T[i]=ch;
ch=getchar();
}
T[0]=i-1; // T[0]用于存储模式串中字符个数
pos=Index_KMP(S,T,0); // 请填空
printf("%d\n",pos);
}
return 0;
}
```
### 18722 稀疏矩阵的运算
```cpp
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
const int N=1E7;
typedef long long ll;
#define IOS ios::sync_with_stdio(0),cin.tie(0);
struct point{
int row;
int col;
int val;
point(){row=2,col=0,val=0;}
};
vector<point> a(N);
bool cmp(point a,point b){
if(a.row != b.row){
return a.row<b.row;
}
else return a.col<b.col;
}
int main(){
IOS;
int n,m,k;
cin>>n>>m>>k;
for(int i=0;i<k;i++){
cin>>a[i].row>>a[i].col>>a[i].val;
swap(a[i].row,a[i].col);
}
sort(a.begin(),a.begin()+k,cmp);
for(int i=0;i<k;i++){
cout<<a[i].row<<' ';
cout<<a[i].col<<' ';
cout<<a[i].val;
cout<<endl;
}
return 0;
}
```
### 18769 不完整的排序
```cpp
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
const int N=1E5;
typedef long long ll;
#define IOS ios::sync_with_stdio(0),cin.tie(0);
int main(){
IOS;
int T,n,a[N];
cin>>T;
while(T--){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
int i=0,j=n-1;
while(i<j){
while(a[i]<0&&i<j) i++;
while(a[j]>0&&j>i) j--;
swap(a[i],a[j]);
}
for(int i=0;i<n;i++){
cout<<a[i]<<' ';
}
cout<<endl;
}
return 0;
}
```
## 实验4
### 8606 二叉树的构建及遍历操作
```cpp
#include "stdio.h"
#include "malloc.h"
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef char ElemType;
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;//左右孩子指针
} BiTNode,*BiTree;
Status CreateBiTree(BiTree &T) { // 算法6.4
// 按先序次序输入二叉树中结点的值(一个字符),’#’字符表示空树,
// 构造二叉链表表示的二叉树T。
char ch;
scanf("%c",&ch);
if (ch=='#') T = NULL;
else {
if (!(T = (BiTNode *)malloc(sizeof(BiTNode)))) return ERROR;
T->data = ch; // 生成根结点
CreateBiTree(T->lchild);// 构造左子树
CreateBiTree(T->rchild); // 构造右子树
}
return OK;
} // CreateBiTree
Status PreOrderTraverse( BiTree T) {
if(T){
printf("%c",T->data);// 前序遍历二叉树T的递归算法
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);//补全代码,可用多个语句
}
return OK;
} // PreOrderTraverse
Status InOrderTraverse( BiTree T) {
if(T){
InOrderTraverse(T->lchild);
printf("%c",T->data);// 中序遍历二叉树T的递归算法
InOrderTraverse(T->rchild);//补全代码,可用多个语句
}
return OK;
} // InOrderTraverse
Status PostOrderTraverse( BiTree T) {
if(T){
PostOrderTraverse(T->lchild);// 后序遍历二叉树T的递归算法
PostOrderTraverse(T->rchild);//补全代码,可用多个语句
printf("%c",T->data);
}
return OK;
} // PostOrderTraverse
int main() //主函数
{
BiTree T;
CreateBiTree(T);
PreOrderTraverse(T);
printf("\n");
InOrderTraverse(T);
printf("\n");
PostOrderTraverse(T);
return 0;//补充代码
}//main
```
### 17121 求二叉树各种节点数
```cpp
#include "stdio.h"
#include "malloc.h"
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
int x1,x2,x3;
typedef char ElemType;
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchild;//左右孩子指针
} BiTNode,*BiTree;
Status CreateBiTree(BiTree &T) { // 算法6.4
// 按先序次序输入二叉树中结点的值(一个字符),’#’字符表示空树,
// 构造二叉链表表示的二叉树T。
char ch;
scanf("%c",&ch);
if (ch=='#') T = NULL;
else {
if (!(T = (BiTNode *)malloc(sizeof(BiTNode)))) return ERROR;
T->data = ch; // 生成根结点
CreateBiTree(T->lchild); // 构造左子树
CreateBiTree(T->rchild); // 构造右子树
}
return OK;
} // CreateBiTree
void PreOrdertree(BiTree &T){
if(T){
if((!(T->lchild==NULL)) + (!(T->rchild == NULL)) == 2){
x1++;
}else if((!(T->lchild==NULL)) + (!(T->rchild == NULL)) == 1){
x2++;
}else{
x3++;
}
PreOrdertree(T->lchild);
PreOrdertree(T->rchild);
}
}
int main() //主函数
{
BiTree T;
CreateBiTree(T);
PreOrdertree(T);
printf("%d\n",x1);
printf("%d\n",x2);
printf("%d\n",x3);
return 0;
}//main
```
### 18924 二叉树的宽度
```cpp
#include "stdio.h"
#include "malloc.h"
int level[60];
struct TreeNode{
int p;
int lchild;
int rchild;
};
TreeNode tree[60];
void Creatbittree(int p,int c){
tree[c].p = p;
if(!tree[p].lchild){
tree[p].lchild = c;
}else{
tree[p].rchild = c;
}
}
void kuandu(int root,int val){
level[val]++;
if(tree[root].lchild){
kuandu(tree[root].lchild,val+1);
}
if(tree[root].rchild){
kuandu(tree[root].rchild,val+1);
}
}
int main() //主函数
{
int T,tmp1,tmp2,root,ans=0;
scanf("%d",&T);
for(int i=1;i<T;i++){
scanf("%d %d",&tmp1,&tmp2);
Creatbittree(tmp1,tmp2);
}
for(int i=1;i<=T;i++){
if(tree[i].p==0){
root = i;
break;
}
}
kuandu(root,1);
for(int i=1;i<60;i++){
if(level[i]>=ans){
ans = level[i];
}
}
printf("%d",ans);
return 0;
}//main
```
```cpp
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
typedef struct tree{
int lchild=0;
int rchild=0;
}tree;
int main() //主函数
{
int n;
int x,y;
tree T[150];
cin>>n;
for(int i=1;i<n;i++){
cin>>x>>y;
if(!T[x].lchild) T[x].lchild=y;
else T[x].rchild=y;
}
int ans=1;//初始化为最小值
queue<int> q;
q.push(1);
while(q.size()){
int len=q.size();
ans = max(ans,len);
for(int i=1;i<=len;i++){
int t=q.front();
q.pop();
if(T[t].lchild) q.push(T[t].lchild);
if(T[t].rchild) q.push(T[t].rchild);//这里并不是二选一,而是有就选
}
}
cout<<ans<<endl;
return 0;
}//main
```
### 18724 二叉树的遍历运算
```cpp
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
using namespace std;
void Traverse(string pre,string in)
{
if(pre=="\0" || in=="\0")
return;
int pos=in.find(pre[0]);//根据先序找到根结点在中序的位置
Traverse(pre.substr(1,pos),in.substr(0,pos));//左子树
Traverse(pre.substr(pos+1),in.substr(pos+1));//右子树
cout<<pre[0];
}
int main()
{
string pre,in;
cin >> pre >> in;
Traverse(pre,in);
return 0;
}
```
### 18923 二叉树的直径
```cpp
#include <iostream>
#define For(i,a,b) for(int i=a;i<b;i++)
using namespace std;
typedef struct treenode
{
int pn;//双亲结点所在下标
int lchild=0;//左孩子
int rchild=0;//右孩子
int maxlen=1;//以该结点为根节点的子树的深度
} Tree;
Tree t[10005];
//A用于按输入顺序存储结点
int A[10005];
int main()
{
int Ans=0,j=0;
int n;
cin>>n;
For(i,1,n)
{
int p,c;
cin>>p>>c;
if(i==1)
A[j++]=p;
if(!t[p].lchild)//p的左孩子为空
{
t[c].pn=p;
t[p].lchild=c;
}
else
{
t[c].pn=p;
t[p].rchild=c;
}
A[j++]=c;
}
for(int i=j-1;i>=0;i--)
{
int l=0,r=0;
if(t[A[i]].lchild)
l=t[t[A[i]].lchild].maxlen;//左子树的深度
if(t[A[i]].rchild)
r=t[t[A[i]].rchild].maxlen;//右子树的深度
t[A[i]].maxlen=max(l+1,r+1);//A[i]结点为根节点的子树的深度
//A[i]结点为根节点的子树的最大二叉树直径
if(Ans<l+r)
Ans=l+r;
}
cout<<Ans<<endl;
return 0;
}
```
```cpp
#include <iostream>
typedef long long ll;
using namespace std;
int n,child[105][3],ans=0;
int dfs(int root)
{
if(!root)
return 0;
int lchild=dfs(child[root][1]),rchild=dfs(child[root][2]);
int len=max(lchild,rchild)+1;
ans=max(ans,lchild+rchild);
return len;
}
int main()
{
int i,j,x,y;
cin>>n;
for(i=1; i<n; i++)
{
cin>>x>>y;
if(!child[x][1])
child[x][1]=y;
else
child[x][2]=y;
}
dfs(1);
cout<<ans;
return 0;
}
```
### 8609 哈夫曼树
```cpp
```
## 实验5
### 8610 顺序查找
```cpp
#include"malloc.h" /* malloc()等 */
#include"stdio.h"
#include"stdlib.h"
typedef int ElemType;
typedef struct /*静态查找表的顺序存储结构 */
{
ElemType *elem; /* 数据元素存储空间基址,建表时按实际长度分配,0号单元留空 */
int length; /* 表长度 */
}SSTable;
void Creat_Seq(SSTable &ST,int n)
{ /* 操作结果: 构造一个含n个数据元素的静态顺序查找表ST(数据来自数组r) */
int i,temp;
ST.elem=(ElemType *)malloc((n+1) * sizeof(ElemType)); /* 动态生成n个数据元素空间(0号单元不用) */
if(!(ST).elem)
{
printf("ERROR\n");
exit(0);
} /*内存分配失败结束程序*/
for(i=1;i<=n;i++)
{
scanf("%d",&temp);
*(ST.elem+i)=temp; /* 依次赋值给ST */
}
ST.length=n;
}
int Search_Seq(SSTable &ST,ElemType key)
{ /* 在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为 */
/* 该元素在表中的位置,否则为0。算法9.1 */
for(int i=ST.length;i>=1;i--){
if(ST.elem[i]==key){
return i;
}
}
return 0;
}
main()
{
SSTable ST;
int loc,key;
int n;
scanf("%d",&n);
Creat_Seq(ST,n);
//printf("Please input the key value:");
scanf("%d",&key);
loc = Search_Seq(ST,key);
if(loc!=0)
printf("The element position is %d.\n",loc);
else
printf("The element is not exist.\n");
}
```
### 8621 二分查找
```cpp
#include"malloc.h" /* malloc()等 */
#include"stdio.h"
#include"stdlib.h"
const int N=1E6;
int a[N],n,flag=0;
int Search_Seq(int a[],int key)
{ /* 在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为 */
/* 该元素在表中的位置,否则为0。算法9.1 */
if(key<a[0] || key>a[n]){
return 0;
}
int l=0,r=n+1,mid;
while(l+1!=r){
mid = (l+r)/2;
if(a[mid] < key){
l=mid;
}else{
r=mid;
}
}
if(a[l+1]!=key){
return 0;
}
return l+1;
}
int main()
{
int loc,key;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
}
scanf("%d",&key);
loc = Search_Seq(a,key);
if(loc)//不能用loc的返回值来确定position是否存在,因为position可以等于0
printf("The element position is %d.\n",loc-1);
else
printf("The element is not exist.\n");
return 0;
}
#include"malloc.h" /* malloc()等 */
#include"stdio.h"
#include"stdlib.h"
const int N=1E6;
int a[N],n,flag=0;
int Search_Seq(int a[],int key)
{ /* 在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为 */
/* 该元素在表中的位置,否则为0。算法9.1 */
if(key>a[n] || key<a[1]){
return 0;
}
int l=0,r=n+1,mid;
while(l+1!=r){
mid = (l+r)/2;
if(a[mid] < key){
l=mid;
}else{
r=mid;
}
}
if(a[l]<key&&a[l+1]>key){
if(l==0&&a[l]==key){
flag=1;
return l;
}
return 0;
}
flag=1;
return l;
}
int main()
{
int loc,key;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
}
scanf("%d",&key);
loc = Search_Seq(a,key);
if(flag)
printf("The element position is %d.\n",loc);
else
printf("The element is not exist.\n");
return 0;
}
```
### 8622 哈希查找
```cpp
#include"malloc.h" /* malloc()等 */
#include"stdlib.h" /* exit() */
#include"stdio.h"
#define EQ(a,b) ((a)==(b))
#define SUCCESS 1
#define UNSUCCESS 0
#define NULLKEY -1 /*哈希表无元素时值为-1*/
typedef int ElemType;
int length;
typedef struct
{
ElemType *elem; /* 数据元素存储基址,动态分配数组 */
int count; /* 当前数据元素个数 */
}HashTable;
void InitHashTable(HashTable *H)
{ /* 操作结果: 构造一个长度为length的哈希表,length为全局变量 */
int i;
(*H).count=0; /* 当前元素个数为0 */
(*H).elem=(ElemType*)malloc(length*sizeof(ElemType));
if(!(*H).elem)
exit(0); /* 存储分配失败 */
for(i=0;i<length;i++)
(*H).elem[i]=NULLKEY; /* 未填记录的标志 */
}
unsigned Hash(ElemType K)
{ /* 一个简单的哈希函数*/
return K = K*3%length;
}
void collision(int *p) /*线性探测再散列 */
{ /* 开放定址法处理冲突 */
((*p)++)%length;
}
int SearchHash(HashTable H,ElemType K,int *p,int *c)
{ /* 在开放定址哈希表H中查找关键码为K的元素,若查找成功,以p指示待查数据 */
/* 元素在表中位置,并返回SUCCESS;否则,以p指示插入位置,并返回UNSUCCESS */
/* c用以计冲突次数,其初值置零,供建表插入时参考。算法9.17 */
*p=Hash(K); /* 求得哈希地址 */
while(H.elem[*p]!=NULLKEY&&!EQ(K,H.elem[*p]))
{ /* 该位置中填有记录,并且关键字不相等 */
(*c)++;
if(*c<length)
collision(p); /* 求得下一探查地址p */
else
break;
}
if EQ(K,H.elem[*p])
return SUCCESS; /* 查找成功,p返回待查数据元素位置 */
else
return UNSUCCESS; /* 查找不成功(H.elem[p].key==NULLKEY),p返回的是插入位置 */
}
int InsertHash(HashTable *H,ElemType e)
{ /* 查找不成功时插入数据元素e到开放定址哈希表H中,并返回查找长度 */
int c,p;
c=0;
if(SearchHash(*H,e,&p,&c)) /* 表中已有与e有相同关键字的元素 */
printf("哈希表中已有元素%d。\n",e);
else{ /* 插入e */
(*H).elem[p]=e;
++(*H).count;
}
return c+1; /*查找长度为冲突次数加1*/
}
void TraverseHash(HashTable H)
{ /* 按哈希地址的顺序打印哈希表,无元素位置用X表示 */
int i;
//printf("HashTable Address:0~%d\n",length-1);
for(i=0;i<length;i++)
if(H.elem[i]==NULLKEY) /* 有数据 */
printf("X ");
else
printf("%d ",H.elem[i]);
printf("\n");
}
main()
{
float i=0,j=0;
ElemType e;
HashTable H;
//printf("Input Table length:");
scanf("%d",&length);
InitHashTable(&H);
//printf("Input key words sequence, -1 conclusion input:");
scanf("%d",&e);
while(e!=-1)
{
j ++; /*j记录输入元素个数*/
i = i + InsertHash(&H,e); /*i记录查找长度的和*/
scanf("%d",&e);
}
TraverseHash(H);
printf("Average search length=%f\n",i/j);
}
```
### 8638 直接插入排序(8639 折半插入排序)
```cpp
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
int main() {
int n,k,j;
vector<int> a;
cin>>n;
for(int i=1;i<=n;i++){
cin>>k;
a.push_back(k);
}
for(int i=1;i<n;i++){
k = a[i];
for(j=i-1;j>=0&&k<=a[j];j--){
a[j+1] = a[j];
}
a[j+1] = k;
for(int k=0;k<n;k++){
cout<<a[k]<<" ";
}
cout<<endl;
}
return 0;
}
```
### 8640 希尔(shell)排序
```cpp
void shell_sort(vector<int> a){
int j,tmp;
for(int gap = a.size()/2;gap>0;gap/=2){
for(int i=gap;i<a.size();i++){
tmp=a[i];
for(j=i-gap;j>=0&&a[j]>tmp;j-=gap){
a[j+gap] = a[j];
}
a[j+gap] = tmp;
}
for(auto x:a) cout<<x<<" ";
cout<<endl;
}
}
```
### 8641 冒泡排序
```cpp
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
using namespace std;
int main() {
int n,k,j;
vector<int> a;
cin>>n;
for(int i=1;i<=n;i++){
cin>>k;
a.push_back(k);
}
bool sorted = false;
for(int i=1;i<n&&!sorted;i++){
sorted=true;
for(int j=0;j<n-1;j++){
if(a[j]>a[j+1]){
swap(a[j],a[j+1]);
sorted = false;
}
}
for(int k=0;k<n;k++){
cout<<a[k]<<" ";
}
cout<<endl;
}
return 0;
}```
### 8642 快速排序
```cpp
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5;
int n;
void insert_sort(int a[],int n){
int i,j,temp;
for(i=1;i<n;i++){
temp =a[i];
for(j=i-1;temp<=a[j]&&j>=0;j--){
a[j+1] = a[j];
}
a[j+1] = temp;
for(int j=0;j<n;j++){
cout<<a[j]<<" ";
}
cout<<endl;
}
}
void shell1_sort(int a[],int n){
int gap = n,temp,j;
while(gap>=1){
gap/=2;
if(gap<1) break;
for(int i=gap;i<n;i++){
temp = a[i];
for(j=i-gap;j>=0&&a[j]>a[i];j-=gap){
a[j+gap] = a[j];
}
a[j+gap] = temp;
}
for(int j=0;j<n;j++){
cout<<a[j]<<" ";
}
cout<<endl;
}
}
void shell2_sort(int arr[], int len)
{
int i, j, gap, key;
for(gap = len / 2; gap > 0; gap = gap / 2)
{
for(i = gap; i < len; i ++)
{
j = i - gap;
key = arr[i];
while(j >= 0 && arr[j] > key)
{
arr[j + gap] = arr[j];
j -= gap;
}
arr[j + gap] = key;
}
for(int j=0;j<len;j++){
cout<<arr[j]<<" ";
}
cout<<endl;
}
}
void bubble_sort(int a[],int len){
for(int i=0;i<len-1;i++){
int flag = 1;
for(int j=0;j<len-1-i;j++){
if(a[j]>a[j+1]){
swap(a[j],a[j+1]);
flag=0;
}
}
for(int j=0;j<len;j++){
cout<<a[j]<<" ";
}
cout<<endl;
if(flag) return;
}
}
//int partition(vector<int>& arr, int left, int right) {
// int pivot = arr[left];
// while (left < right) {
// while (left < right && arr[right] >= pivot) {
// right--;
// }
// arr[left] = arr[right];
// while (left < right && arr[left] <= pivot) {
// left++;
// }
// arr[right] = arr[left];
// }
// arr[left] = pivot;
// return left;
//}
//
//void quick_sort(vector<int>& arr, int left, int right) {
// if (left < right) {
// int pivot_index = partition(arr, left, right);
// for (int i = 0; i < arr.size(); i++) {
// cout << arr[i] << " ";
// }
// cout << endl;
// quick_sort(arr, left, pivot_index - 1);
// quick_sort(arr, pivot_index + 1, right);
// }
//}
int partition(int a[],int left,int right){
int pivot=a[left];
while(left<right){
while(left<right&&a[right]>=pivot){//注意等号
right--;
}
a[left] = a[right];
while(left<right&&a[left]<=pivot){
left++;
}
a[right] = a[left];
}
a[left] = pivot;
return left;
}
void quick_sort(int a[],int left,int right){
if(left<right){
int pivot_index = partition(a,left,right);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
quick_sort(a,left,pivot_index-1);
quick_sort(a,pivot_index+1,right);
}
}
int main() {
int a[N];
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
quick_sort(a,0,n-1);
return 0;
}
```
### 8643 简单选择排序
```cpp
void select_sort(int a[],int n){
for(int i=0;i<n-1;i++){
int min_index = i;
for(int j=i+1;j<n;j++){
if(a[j]<a[min_index]){
min_index = j;
}
}
swap(a[i],a[min_index]);
for(int k=0;k<n;k++){
cout<<a[k]<<" ";
}
cout<<endl;
}
}
int main() {
int a[N];
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
select_sort(a,n);
return 0;
}
```
### 8644 堆排序
```cpp
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e5;
int n,tmp[N];
void insert_sort(int a[],int n){
int i,j,temp;
for(i=1;i<n;i++){
temp =a[i];
for(j=i-1;temp<=a[j]&&j>=0;j--){
a[j+1] = a[j];
}
a[j+1] = temp;
for(int j=0;j<n;j++){
cout<<a[j]<<" ";
}
cout<<endl;
}
}
void shell1_sort(int a[],int n){
int gap = n,temp,j;
while(gap>=1){
gap/=2;
if(gap<1) break;
for(int i=gap;i<n;i++){
temp = a[i];
for(j=i-gap;j>=0&&a[j]>a[i];j-=gap){
a[j+gap] = a[j];
}
a[j+gap] = temp;
}
for(int j=0;j<n;j++){
cout<<a[j]<<" ";
}
cout<<endl;
}
}
void shell2_sort(int arr[], int len)
{
int i, j, gap, key;
for(gap = len / 2; gap > 0; gap = gap / 2)
{
for(i = gap; i < len; i ++)
{
j = i - gap;
key = arr[i];
while(j >= 0 && arr[j] > key)
{
arr[j + gap] = arr[j];
j -= gap;
}
arr[j + gap] = key;
}
for(int j=0;j<len;j++){
cout<<arr[j]<<" ";
}
cout<<endl;
}
}
void bubble_sort(int a[],int len){
for(int i=0;i<len-1;i++){
int flag = 1;
for(int j=0;j<len-1-i;j++){
if(a[j]>a[j+1]){
swap(a[j],a[j+1]);
flag=0;
}
}
for(int j=0;j<len;j++){
cout<<a[j]<<" ";
}
cout<<endl;
if(flag) return;
}
}
//int partition(vector<int>& arr, int left, int right) {
// int pivot = arr[left];
// while (left < right) {
// while (left < right && arr[right] >= pivot) {
// right--;
// }
// arr[left] = arr[right];
// while (left < right && arr[left] <= pivot) {
// left++;
// }
// arr[right] = arr[left];
// }
// arr[left] = pivot;
// return left;
//}
//
//void quick_sort(vector<int>& arr, int left, int right) {
// if (left < right) {
// int pivot_index = partition(arr, left, right);
// for (int i = 0; i < arr.size(); i++) {
// cout << arr[i] << " ";
// }
// cout << endl;
// quick_sort(arr, left, pivot_index - 1);
// quick_sort(arr, pivot_index + 1, right);
// }
//}
int partition(int a[],int left,int right){
int pivot=a[left];
while(left<right){
while(left<right&&a[right]>=pivot){//注意等号
right--;
}
a[left] = a[right];
while(left<right&&a[left]<=pivot){
left++;
}
a[right] = a[left];
}
a[left] = pivot;
return left;
}
void quick_sort(int a[],int left,int right){
if(left<right){
int pivot_index = partition(a,left,right);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
quick_sort(a,left,pivot_index-1);
quick_sort(a,pivot_index+1,right);
}
}
void select_sort(int a[],int n){
for(int i=0;i<n-1;i++){
int min_index = i;
for(int j=i+1;j<n;j++){
if(a[j]<a[min_index]){
min_index = j;
}
}
swap(a[i],a[min_index]);
for(int k=0;k<n;k++){
cout<<a[k]<<" ";
}
cout<<endl;
}
}
void merge_sort(int q[], int l, int r)//递归归并
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
for(int m=0;m<n;m++){
cout<<q[m]<<" ";
}
cout<<endl;
}
void HeapAdjust(int* arr, int start, int end)//下滤法,从上往下不断筛选
{
int root=arr[start];//记录根值,左孩子为2*i,右孩子为2*i+1;
for(int j=2*start;j<=end;j*=2){//start为根,j表示左孩子,不断寻找左孩子
if(j<end && arr[j] < arr[j+1]) j++;//左孩子小于右孩子,找到大孩子
if(root >= arr[j]) continue;//如果根的值
arr[start] = arr[j];
start = j;
}
arr[start] = root;
}
void creat_heap(int* a,int length){
for(int i = length/2;i>0;--i){
HeapAdjust(a,i,length);
}
}
void heap_sort(int* arr, int len)
{
creat_heap(arr,len);
for(int i=len;i>1;i--){
for(int k=1;k<=len;k++){
cout<<arr[k]<<" ";
}
cout<<endl;
swap(arr[i],arr[1]);
HeapAdjust(arr,1,i-1);
}
for(int k=1;k<=len;k++){
cout<<arr[k]<<" ";
}
}
int main() {
int a[N];
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
heap_sort(a,n);
return 0;
}
```
### 8645 归并排序(非递归算法)
```cpp
#include <iostream>
#include <vector>
using namespace std;
void merge(vector<int>& arr, int left, int mid, int right) {
vector<int> temp(right - left + 1); // 临时数组,用来存储归并后的结果
int i = left, j = mid + 1, k = 0;
while (i <= mid && j <= right) { // 比较左右两部分的元素,将较小的元素放入临时数组中
if (arr[i] <= arr[j]) {
temp[k++] = arr[i++];
} else {
temp[k++] = arr[j++];
}
}
while (i <= mid) { // 将剩余的元素放入临时数组中
temp[k++] = arr[i++];
}
while (j <= right) { // 将剩余的元素放入临时数组中
temp[k++] = arr[j++];
}
for (int i = 0; i < k; i++) { // 将临时数组中的元素复制回原数组
arr[left + i] = temp[i];
}
}
void merge_sort(vector<int>& arr, int n) {
for (int step = 1; step < n; step *= 2) { // 步长从1开始,每次*2,直到大于等于n
for (int left = 0; left < n - step; left += step * 2) { // 每次对两个步长为step的子序列进行归并
int mid = left + step - 1;
int right = min(left + step * 2 - 1, n - 1);
merge(arr, left, mid, right);
}
for (int i = 0; i < n; i++) { // 输出每趟排序结果
cout << arr[i] << " ";
}
cout << endl;
}
}
int main() {
int n;
cin >> n;
vector<int> arr(n);
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
merge_sort(arr, n);
return 0;
}
```
### 8646 基数排序
```cpp
//#include <iostream>
//#include <cmath>
//#include <vector>
//
//using namespace std;
//
获取数组中最大的数字的位数
//int getMaxDigit(vector<int> &nums) {
// int maxNum = 0;
// for (int num : nums) {
// maxNum = max(maxNum, num);
// }
// int digit = 0;
// while (maxNum > 0) {
// maxNum /= 10;
// digit++;
// }
// return digit;
//}
//
按照第d位进行排序
//void radixSort(vector<int> &nums, int d) {
// //10个桶
// vector<vector<int>> buckets(10);
//
// //计算每一个数的第d位的值
// for (int num : nums) {
// int digit = (num / ((int)pow(10, d-1))) % 10;
// buckets[digit].push_back(num);
// }
//
// //把桶中的数放回nums
// nums.clear();
// for (vector<int> bucket : buckets) {
// for (int num : bucket) {
// nums.push_back(num);
// }
// }
//}
//
基数排序
//void radixSort(vector<int> &nums) {
// //获取最大位数
// int digit = getMaxDigit(nums);
//
// //进行digit次排序
// for (int d = 1; d <= digit; d++) {
// radixSort(nums, d);
// }
//}
//
//int main() {
// int n;
// cin >> n;
// vector<int> nums(n);
// for (int i = 0; i < n; i++) {
// cin >> nums[i];
// }
//
// //基数排序
// radixSort(nums);
//
// //输出结果
// for (int num : nums) {
// cout << num << " ";
// }
// cout << endl;
//}
#include <iostream>
#include <cstring>
#include <cmath>
using namespace std;
int temp[100];
int bucket[10];
int maxBit(int data[],int n)
{
int maxData = data[0];
for(int i=1;i<n;i++)
{
if(maxData<data[i])
maxData=data[i];
}
int d=1;
while(maxData>=10)
{
maxData/=10;
d++;
}
return d;
}
void radixsort(int data[],int n)
{
int d = maxBit(data,n);
int i,j,k;
int radix = 1;
for(i=1;i<=d;i++)
{
for(j=0;j<10;j++)
{
bucket[j]=0;
}
for(j=0;j<n;j++)
{
k=(data[j]/radix)%10;
bucket[k]++;
}
for(j = 1; j < 10; j++)
bucket[j] = bucket[j - 1] + bucket[j];
for(j = n-1; j>=0; j--)
{
k = (data[j] / radix) % 10;
temp[bucket[k] - 1] = data[j];
bucket[k]--;
}
for(j = 0; j < n; j++){
int tmp=temp[j];
for(int k=d-1;k>=0;k--){
cout<<tmp/int(pow(10,k));
tmp%=int(pow(10,k));
}
cout<<" ";
}
cout << endl;
for(j = 0; j < n; j++)
data[j] = temp[j];
radix = radix * 10;
}
}
int main()
{
int n, data[100];
cin >> n;
for(int i = 0; i < n; i++)
cin >> data[i];
radixsort(data, n);
return 0;
}
```
## 实验7
### 8647 实现图的存储结构
```cpp
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <utility>
#include <vector>
#include <cmath>
using namespace std;
const int N = 1e3;
typedef long long ll;
#define IOS ios::sync_with_stdio(0),cin.tie(0)
int a[N][N];
int main(){
IOS;
int n,m,i,j;
cin>>n>>m;
while(m--){
cin>>i>>j;
a[i-1][j-1]=1;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
```
### 8648 图的深度遍历
```cpp
#include"string.h"
#include"malloc.h" /* malloc()等 */
#include"stdio.h" /* EOF(=^Z或F6),NULL */
#include"stdlib.h" /* exit() */
typedef int InfoType; /* 顶点权值类型 */
#define MAX_NAME 3 /* 顶点字符串的最大长度+1 */
typedef char VertexType[MAX_NAME]; /* 字符串类型 */
/*图的邻接表存储表示 */
#define MAX_VERTEX_NUM 20
typedef enum{DG,DN,AG,AN}GraphKind; /* {有向图,有向网,无向图,无向网} */
typedef struct ArcNode
{
int adjvex; /* 该弧所指向的顶点的位置 */
struct ArcNode *nextarc; /* 指向下一条弧的指针 */
InfoType *info; /* 网的权值指针) */
}ArcNode; /* 表结点 */
typedef struct
{
VertexType data; /* 顶点信息 */
ArcNode *firstarc; /* 第一个表结点的地址,指向第一条依附该顶点的弧的指针 */
}VNode,AdjList[MAX_VERTEX_NUM]; /* 头结点 */
typedef struct
{
AdjList vertices;//邻接表
int vexnum,arcnum; /* 图的当前顶点数和弧数 */
int kind; /* 图的种类标志 */
}ALGraph;
int LocateVex(ALGraph G,VertexType u)
{ /* 初始条件: 图G存在,u和G中顶点有相同特征 */
/* 操作结果: 若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */
int i;
for(i=0;i<G.vexnum;++i)
if(strcmp(u,G.vertices[i].data)==0)
return i;
return -1;
}
void CreateGraph(ALGraph *G)
{ /* 采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4种图) */
int i,j,k;
int w; /* 权值 */
VertexType va,vb;
ArcNode *p;
//printf("Enter the type of map:(0~3): ");
scanf("%d",&(*G).kind);
//printf("Enter Vertex number,Arc number: ");
scanf("%d%d",&(*G).vexnum,&(*G).arcnum);
//printf("Enter %d Vertex :\n",(*G).vexnum);
for(i=0;i<(*G).vexnum;++i) /* 构造顶点向量 */
{
scanf("%s",(*G).vertices[i].data);
(*G).vertices[i].firstarc=NULL;
}
//if((*G).kind==1||(*G).kind==3) /* 网 */
// printf("Enter order every arc weight,head and tail (Takes the gap by the blank space ):\n");
//else /* 图 */
// printf("Enter order every arc head and tail (Takes the gap by the blank space ):\n");
for(k=0;k<(*G).arcnum;++k) /* 构造表结点链表 */
{
if((*G).kind==1||(*G).kind==3) /* 网 */
scanf("%d%s%s",&w,va,vb);
else /* 图 */
scanf("%s%s",va,vb);
i=LocateVex(*G,va); /* 弧尾 */
j=LocateVex(*G,vb); /* 弧头 */
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;
if((*G).kind==1||(*G).kind==3) /* 网 */
{
p->info=(int *)malloc(sizeof(int));
*(p->info)=w;
}
else
p->info=NULL; /* 图 */
p->nextarc=(*G).vertices[i].firstarc; /* 插在表头 */
(*G).vertices[i].firstarc=p;
if((*G).kind>=2) /* 无向图或网,产生第二个表结点 */
{
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=i;
if((*G).kind==3) /* 无向网 */
{
p->info=(int*)malloc(sizeof(int));
*(p->info)=w;
}
else
p->info=NULL; /* 无向图 */
p->nextarc=(*G).vertices[j].firstarc; /* 插在表头 */
(*G).vertices[j].firstarc=p;
}
}
}
VertexType* GetVex(ALGraph G,int v)
{ /* 初始条件: 图G存在,v是G中某个顶点的序号。操作结果: 返回v的值 */
if(v>=G.vexnum||v<0)
exit(0);
return &G.vertices[v].data;
}
int FirstAdjVex(ALGraph G,VertexType v)
{ /* 初始条件: 图G存在,v是G中某个顶点 */
/* 操作结果: 返回v的第一个邻接顶点的序号。若顶点在G中没有邻接顶点,则返回-1 */
ArcNode *p;
int v1;
v1=LocateVex(G,v); /* v1为顶点v在图G中的序号 */
p=G.vertices[v1].firstarc;
if(p)
return p->adjvex;
else
return -1;
}
int NextAdjVex(ALGraph G,VertexType v,VertexType w)
{ /* 初始条件: 图G存在,v是G中某个顶点,w是v的邻接顶点 */
/* 操作结果: 返回v的(相对于w的)下一个邻接顶点的序号。 */
/* 若w是v的最后一个邻接点,则返回-1 */
ArcNode *p;
int v1,w1;
v1=LocateVex(G,v); /* v1为顶点v在图G中的序号 */
w1=LocateVex(G,w); /* w1为顶点w在图G中的序号 */
p=G.vertices[v1].firstarc;
while(p&&p->adjvex!=w1) /* 指针p不空且所指表结点不是w */
p=p->nextarc;
if(!p||!p->nextarc) /* 没找到w或w是最后一个邻接点 */
return -1;
else /* p->adjvex==w */
return p->nextarc->adjvex; /* 返回v的(相对于w的)下一个邻接顶点的序号 */
}
/*深度遍历*/
int visited[MAX_VERTEX_NUM]; /* 访问标志数组(全局量),未访问标记0,访问标记1 */
void(*VisitFunc)(char* v); /* 函数变量(全局量) */
void DFS(ALGraph G,int v)
{ /* 从第v个顶点出发递归地深度优先遍历图G。算法7.5 */
/* 设置访问标志为TRUE(已访问) */
/* 访问第v个顶点 */
/* 对v的尚未访问的邻接点w递归调用DFS
*/
visited[v] = true;
VisitFunc(G.vertices[v].data);
for(int w = FirstAdjVex(G,G.vertices[v].data);w>0;w=NextAdjVex(G,G.vertices[v].data,G.vertices[w].data)){
if(!visited[w]) DFS(G,w);
}
}
void print(char* i){
printf("%s ",i);
}
void DFSTraverse(ALGraph G,void(*Visit)(char*))
{ /* 对图G作深度优先遍历。算法7.4 */
/* 使用全局变量VisitFunc,使DFS不必设函数指针参数 */
/* 访问标志数组初始化 */
/* 对尚未访问的顶点调用DFS */
VisitFunc = Visit;
for(int v=0;v<G.vexnum;v++) visited[v] = false;
for(int v=0;v<G.vexnum;v++) {
if(!visited[v]) DFS(G,v);
}
printf("\n");
}
int main()
{
ALGraph g;
CreateGraph(&g);
DFSTraverse(g,print);
return 1;
}
```
### 8649 图的广度遍历
```cpp
#include"string.h"
#include"malloc.h" /* malloc()等 */
#include"stdio.h" /* EOF(=^Z或F6),NULL */
#include"stdlib.h" /* exit() */
typedef int InfoType; /* 顶点权值类型 */
#define MAX_NAME 3 /* 顶点字符串的最大长度+1 */
typedef char VertexType[MAX_NAME]; /* 字符串类型 */
/*图的邻接表存储表示 */
#define MAX_VERTEX_NUM 20
typedef enum{DG,DN,AG,AN}GraphKind; /* {有向图,有向网,无向图,无向网} */
typedef struct ArcNode
{
int adjvex; /* 该弧所指向的顶点的位置 */
struct ArcNode *nextarc; /* 指向下一条弧的指针 */
InfoType *info; /* 网的权值指针) */
}ArcNode; /* 表结点 */
typedef struct
{
VertexType data; /* 顶点信息 */
ArcNode *firstarc; /* 第一个表结点的地址,指向第一条依附该顶点的弧的指针 */
}VNode,AdjList[MAX_VERTEX_NUM]; /* 头结点 */
typedef struct
{
AdjList vertices;//邻接表
int vexnum,arcnum; /* 图的当前顶点数和弧数 */
int kind; /* 图的种类标志 */
}ALGraph;
int LocateVex(ALGraph G,VertexType u)
{ /* 初始条件: 图G存在,u和G中顶点有相同特征 */
/* 操作结果: 若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 */
int i;
for(i=0;i<G.vexnum;++i)
if(strcmp(u,G.vertices[i].data)==0)
return i;
return -1;
}
void CreateGraph(ALGraph *G)
{ /* 采用邻接表存储结构,构造没有相关信息的图G(用一个函数构造4种图) */
int i,j,k;
int w; /* 权值 */
VertexType va,vb;
ArcNode *p;
//printf("Enter the type of map:(0~3): ");
scanf("%d",&(*G).kind);
//printf("Enter Vertex number,Arc number: ");
scanf("%d%d",&(*G).vexnum,&(*G).arcnum);
//printf("Enter %d Vertex :\n",(*G).vexnum);
for(i=0;i<(*G).vexnum;++i) /* 构造顶点向量 */
{
scanf("%s",(*G).vertices[i].data);
(*G).vertices[i].firstarc=NULL;
}
//if((*G).kind==1||(*G).kind==3) /* 网 */
// printf("Enter order every arc weight,head and tail (Takes the gap by the blank space ):\n");
//else /* 图 */
// printf("Enter order every arc head and tail (Takes the gap by the blank space ):\n");
for(k=0;k<(*G).arcnum;++k) /* 构造表结点链表 */
{
if((*G).kind==1||(*G).kind==3) /* 网 */
scanf("%d%s%s",&w,va,vb);
else /* 图 */
scanf("%s%s",va,vb);
i=LocateVex(*G,va); /* 弧尾 */
j=LocateVex(*G,vb); /* 弧头 */
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=j;
if((*G).kind==1||(*G).kind==3) /* 网 */
{
p->info=(int *)malloc(sizeof(int));
*(p->info)=w;
}
else
p->info=NULL; /* 图 */
p->nextarc=(*G).vertices[i].firstarc; /* 插在表头 */
(*G).vertices[i].firstarc=p;
if((*G).kind>=2) /* 无向图或网,产生第二个表结点 */
{
p=(ArcNode*)malloc(sizeof(ArcNode));
p->adjvex=i;
if((*G).kind==3) /* 无向网 */
{
p->info=(int*)malloc(sizeof(int));
*(p->info)=w;
}
else
p->info=NULL; /* 无向图 */
p->nextarc=(*G).vertices[j].firstarc; /* 插在表头 */
(*G).vertices[j].firstarc=p;
}
}
}
VertexType* GetVex(ALGraph G,int v)
{ /* 初始条件: 图G存在,v是G中某个顶点的序号。操作结果: 返回v的值 */
if(v>=G.vexnum||v<0)
exit(0);
return &G.vertices[v].data;
}
int FirstAdjVex(ALGraph G,VertexType v)
{ /* 初始条件: 图G存在,v是G中某个顶点 */
/* 操作结果: 返回v的第一个邻接顶点的序号。若顶点在G中没有邻接顶点,则返回-1 */
ArcNode *p;
int v1;
v1=LocateVex(G,v); /* v1为顶点v在图G中的序号 */
p=G.vertices[v1].firstarc;
if(p)
return p->adjvex;
else
return -1;
}
int NextAdjVex(ALGraph G,VertexType v,VertexType w)
{ /* 初始条件: 图G存在,v是G中某个顶点,w是v的邻接顶点 */
/* 操作结果: 返回v的(相对于w的)下一个邻接顶点的序号。 */
/* 若w是v的最后一个邻接点,则返回-1 */
ArcNode *p;
int v1,w1;
v1=LocateVex(G,v); /* v1为顶点v在图G中的序号 */
w1=LocateVex(G,w); /* w1为顶点w在图G中的序号 */
p=G.vertices[v1].firstarc;
while(p&&p->adjvex!=w1) /* 指针p不空且所指表结点不是w */
p=p->nextarc;
if(!p||!p->nextarc) /* 没找到w或w是最后一个邻接点 */
return -1;
else /* p->adjvex==w */
return p->nextarc->adjvex; /* 返回v的(相对于w的)下一个邻接顶点的序号 */
}
/*深度遍历*/
int visited[MAX_VERTEX_NUM]; /* 访问标志数组(全局量),未访问标记0,访问标记1 */
void(*VisitFunc)(char* v); /* 函数变量(全局量) */
void DFS(ALGraph G,int v)
{ /* 从第v个顶点出发递归地深度优先遍历图G。算法7.5 */
/* 设置访问标志为TRUE(已访问) */
/* 访问第v个顶点 */
/* 对v的尚未访问的邻接点w递归调用DFS
*/
visited[v] = true;
VisitFunc(G.vertices[v].data);
for(int w = FirstAdjVex(G,G.vertices[v].data);w>0;w=NextAdjVex(G,G.vertices[v].data,G.vertices[w].data)){
if(!visited[w]) DFS(G,w);
}
}
void print(char* i){
printf("%s ",i);
}
void DFSTraverse(ALGraph G,void(*Visit)(char*))
{ /* 对图G作深度优先遍历。算法7.4 */
/* 使用全局变量VisitFunc,使DFS不必设函数指针参数 */
/* 访问标志数组初始化 */
/* 对尚未访问的顶点调用DFS */
VisitFunc = Visit;//对全局变量函数进行赋值,将传入的函数赋值为全局函数,便于DFS函数调用
for(int v=0;v<G.vexnum;v++) visited[v] = false;
for(int v=0;v<G.vexnum;v++) {
if(!visited[v]) DFS(G,v);//如果该节点没有被访问过,就继续找
}
printf("\n");
}
int main()
{
ALGraph g;
CreateGraph(&g);
DFSTraverse(g,print);
return 1;
}
```