SCAU数据结构题解
实验一
8576 顺序线性表的基本操作
#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*/
// 构建顺序表直接按照结构体SqList一个个定义就行
L.elem=new ElemType[LIST_INIT_SIZE+1];// 为顺序表的元素分配内存(相当于构建了一个数组)
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=1; 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;
for(int j=L.length; j>=i; j--)
L.elem[j+1]=L.elem[j];
L.elem[i]=e;
L.length++;//别忘记更新顺序表长度
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;
e=L.elem[i];
for(int j=i; j<=L.length-1; j++)
L.elem[j]=L.elem[j+1];
L.length--; //更新顺序表
return OK;
}
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;
}
}
}
8577 合并顺序表
// 解法一:标准数据结构
#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)
{
L.listsize=LIST_INIT_SIZE;
L.elem=new int[LIST_INIT_SIZE+1];
L.length=0;
return OK;
}
int Load_Sq(SqList &L)
{
if(L.length==0) printf("The List is empty!");
else
{
for(int i=0; i<L.length; ++i)
printf("%d ",L.elem[i]);
}
printf("\n");
return OK;
}
int WrithList_Sq(SqList &L)
{
int n;
scanf("%d",&n);
int tem;
for(int i=0; i<n; i++)
{
scanf("%d",&tem);
L.elem[i]=tem;
L.length++;
}
return OK;
}
int MergeList_Sq(SqList &A,SqList &B) //合并顺序表
{
SqList C;
InitList_Sq(C);
int i=0,j=0,k=0;
while(i<A.length&&j<B.length)
{
if(A.elem[i]<=B.elem[j])
{
C.elem[k++]=A.elem[i++];
C.length++;
}
else
{
C.elem[k++]=B.elem[j++];
C.length++;
}
}
while(B.length>j)
{
C.elem[k++]=B.elem[j++];
C.length++;
}
while(A.length>i)
{
C.elem[k++]=A.elem[i++];
C.length++;
}
printf("List C:");
Load_Sq(C);
return OK;
}
int main()
{
SqList A,B;
InitList_Sq(A);
InitList_Sq(B);
WrithList_Sq(A);
WrithList_Sq(B);
printf("List A:");
Load_Sq(A);
printf("List B:");
Load_Sq(B);
MergeList_Sq(A,B);
return OK;
}
// 解法二:c++数组模拟快速实现
#include <iostream>
using namespace std;
int n,m;
int main()
{
cin>>n;
int a[n+10];
cout<<"List A:";
for(int i=0; i<n; i++) cin>>a[i],cout<<a[i]<<" ";
cout<<'\n';
cin>>m;
int b[m+10];
cout<<"List B:";
for(int j=0; j<m; j++) cin>>b[j],cout<<b[j]<<" ";
cout<<'\n';
int i=0,j=0;
cout<<"List C:";
while(i<n&&j<m) //这里进行一个顺序表归并
if(a[i]<=b[j])
cout<<a[i++]<<" ";
else
cout<<b[j++]<<" ";
while(i<n)
cout<<a[i++]<<" ";
while(j<m)
cout<<b[j++]<<" ";
cout<<'\n';
return 0;
} //看上去很复杂实际上很简单,写这么多行完全是为了迁就输出格式
8578 顺序表逆置
#include<stdio.h>
#include<malloc.h>
#define OK 1
#define ERROR 0
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
#define ElemType int
typedef int Status;
typedef struct
{
int *elem;
int length;
int listsize;
} SqList;
Status InitList_Sq(SqList &L)
{
// 算法2.3
// 构造一个空的线性表L。
L.elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if (!L.elem) return OK; // 存储分配失败
L.length = 0; // 空表长度为0
L.listsize = LIST_INIT_SIZE; // 初始存储容量
return OK;
} // InitList_Sq
Status ListInsert_Sq(SqList &L, int i, ElemType e)
{
// 算法2.4
// 在顺序线性表L的第i个元素之前插入新的元素e,
// i的合法值为1≤i≤ListLength_Sq(L)+1
ElemType *p;
if (i < 1 || i > L.length+1) return ERROR; // i值不合法
if (L.length >= L.listsize) // 当前存储空间已满,增加容量
{
ElemType *newbase = (ElemType *)realloc(L.elem,
(L.listsize+LISTINCREMENT)*sizeof (ElemType));
if (!newbase) return ERROR; // 存储分配失败
L.elem = newbase; // 新基址
L.listsize += LISTINCREMENT; // 增加存储容量
}
ElemType *q = &(L.elem[i-1]); // q为插入位置
for (p = &(L.elem[L.length-1]); p>=q; --p) *(p+1) = *p;
// 插入位置及之后的元素右移
*q = e; // 插入e
++L.length; // 表长增1
return OK;
} // ListInsert_Sq
Status ListDelete_Sq(SqList &L, int i, ElemType &e)
{
// 算法2.5
// 在顺序线性表L中删除第i个元素,并用e返回其值。
// i的合法值为1≤i≤ListLength_Sq(L)。
ElemType *p, *q;
if (i<1 || i>L.length) return ERROR; // i值不合法
p = &(L.elem[i-1]); // p为被删除元素的位置
e = *p; // 被删除元素的值赋给e
q = L.elem+L.length-1; // 表尾元素的位置
for (++p; p<=q; ++p) *(p-1) = *p; // 被删除元素之后的元素左移
--L.length; // 表长减1
return OK;
} // ListDelete_Sq
int WrithList_Sq(SqList &L)
{
int n;
scanf("%d",&n);
int tem;
for(int i=0; i<n; i++)
{
scanf("%d",&tem);
L.elem[i]=tem;
L.length++;
}
return OK;
}
int main()
{
int n;
scanf("%d",&n);
int a[n];
for(int i=0; i<n; i++)
scanf("%d",&a[i]);
printf("The List is:");
for(int i=0; i<n; i++)
printf("%d ",a[i]);
printf("\n");
printf("The turned List is:");
for(int i=n-1; i>=0; i--)
printf("%d ",a[i]);
return 0;
} //感觉完全抽象这题,,给的算法都是啥啊,,不如直接数组倒序输出。
8579 链式线性表的基本操作
#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;
}
p->next=NULL;
//记得一定补充这一句!!把链表结尾指向NULL,不然不知道链表结尾指向哪里去了会导致后续遍历无法终止
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 tem=new LNode; // 先创建一个指针tem指向新的将要插入的结点
tem->data=e; // 结点赋值e
LinkList p; // 建立一个遍历指针p
p=L; // p最开始为头结点(相当于p此时指向第1号位置)
i--;
while(i--)
{
p=p->next;
//printf("%d ",p->data);
}
if(p==NULL)
return ERROR;
else
{
tem->next=p->next;
p->next=tem;
return OK;
}
}
int LinkDelete_L(LinkList &L,int i, ElemType &e)
{
/* 算法2.10
在带头结点的单链线性表L中,删除第i个元素,并用e返回其值 */
LinkList p;
p=L;
i--;
while(i--)
{
p=p->next;
}
if(p->next==NULL)
return ERROR;
else
{
LinkList q=p->next;
e=q->data;
p->next=q->next;
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("Insert Error!\n"); // 判断i值是否合法
else printf("The Element %d is Successfully Inserted!\n", x);
break;
case 2:
scanf("%d",&i);
if(!LinkDelete_L(T,i,e)) printf("Delete Error!\n"); // 判断i值是否合法
else printf("The Element %d is Successfully Deleted!\n", e);
break;
case 3:
LoadLink_L(T);
break;
case 0:
return 1;
}
}
return 0;
}
8580 合并链表
//用之前合并顺序表的代码就能过,原理一样。
19080 反转链表
// 解法一:遍历后不断创建新结点,往回插入
#include <iostream>//C++
using namespace std;
struct LNode
{
int data;
LNode * next;
};
void createList(LNode * &L,int n)
{
/* 尾插法创建单链表 */
LNode *r, *p;
r=L=new LNode;/* 创建头结点 */
L->next=NULL;
for(int i=1; i<=n; i++)
{
p=new LNode;
cin>>p->data;
p->next=NULL;
r->next=p;
r=p;
}
}
void trv(LNode * L)
{
/* 一个简单的链表遍历函数,供编程过程中测试使用 */
L=L->next;
while(L)
{
cout<<L->data<<' ';
L=L->next;
}
}
void reverseList(LNode * &L)
{
//由于题目要求空间和时间复杂度较为严格,本题的思路为:
//遍历链表,没遍历完一个结点,将当前结点插入头指针之后,并将该结点删除
LNode *p=L->next; //p为遍历指针
LNode *ed=new LNode; //插入一个用于终结的空结点
ed->data=p->data;
ed->next=L->next;
L->next=ed;
p=p->next;
//插入第一个数的时候不要在循环里插入,因为第一个插入的结点->next=NULL可以直接用于结束链表,后续要使用,结点比较特殊。
while(p!=NULL)//循环,将遍历到的结点一个个插入进头结点后面,实现倒序
{
LNode *tem=new LNode; // 创建新结点用于存储遍历到的当前结点并插入
tem->data=p->data;
tem->next=L->next;
L->next=tem;
p=p->next;
}
ed->next=NULL;
}
int main()
{
int n;
LNode *L;
cin>>n;
createList(L,n);
reverseList(L);
trv(L);
return 0;
}
// 解法二:另一种比较简单粗暴的方法,利用num记录遍历了多少个数。
// 在完成倒序插入后从头指针遍历num个数,然后->next=NULL将链表结束,断掉剩下的数,实现倒序。
void reverseList(LNode * &L)
{
LNode *ne=L->next,*q=L,*s;
int num=1;
while(1)
{
int e=ne->data;
//插入元素操作
s=new LNode;
s->data=e;
s->next=L->next;
L->next=s;
//插入完成
if(ne->next==NULL) //如果遍历结束直接break停止循环
break;
//p=p->next;
ne=ne->next;
num++;
}
while(num--)
q=q->next;
q->next=NULL;
}
// 解法三:OJ提供的标程:创建新链表
void reverseList(LNode * &L)
{
LNode *pre = NULL;/**< 用三个指针分别表示前驱,当前,后继 */
// pre是新链表的头结点
LNode *cur = L->next;/**< 当前是第一个节点a1 */
LNode *nex = NULL; /**<思考如何用这三个指针实现翻转,另外,三个指针也要同步后移 */
while (cur)
{
nex = cur->next; // nex指针的作用是保存cur的下一个结点,实现链表遍历
cur->next = pre;
pre = cur;
cur = nex; // cur跳到下一个结点
}
L->next=pre; // 将链表L接到新链表pre之前
}
实验二
8583 顺序栈的基本操作
#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,该栈预定义大小为STACK_INIT_SIZE
S.base =new SElemType[STACK_INIT_SIZE];
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack &S,SElemType e)
{
// 在栈S中插入元素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 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的元素个数
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(S.top!=S.base)
{
p=--S.top;
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", StackLength(S));
break;
case 5:
StackTraverse(S);
break;
case 0:
return 1;
}
}
}
8584 循环队列的基本操作
#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 QElemType[MAXQSIZE];
Q.front=0;
Q.rear=Q.front;
return OK;
}
Status EnQueue(SqQueue &Q,QElemType e)
{
// 插入元素e为Q的新的队尾元素
Q.base[Q.rear++]=e;
return OK;
}
Status DeQueue(SqQueue &Q, QElemType &e)
{
// 若队列不空, 则删除Q的队头元素, 用e返回其值, 并返回OK; 否则返回ERROR
if(Q.front==Q.rear)
return ERROR;
e=Q.base[Q.front];
Q.front++;
return OK;
}
Status GetHead(SqQueue Q, QElemType &e)
{
// 若队列不空,则用e返回队头元素,并返回OK,否则返回ERROR
if(Q.front==Q.rear)
return ERROR;
e=Q.base[Q.front];
return OK;
}
int QueueLength(SqQueue Q)
{
// 返回Q的元素个数
return Q.rear-Q.front;
}
Status QueueTraverse(SqQueue Q)
{
// 若队列不空,则从队头到队尾依次输出各个队列元素,并返回OK;否则返回ERROR.
int i;
i=Q.front;
if(!QueueLength(Q))printf("The Queue is Empty!");
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"); // 判断GetHead是否合法
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 栈的应用——进制转换
//解法一:数据结构
#define _CRT_SECURE_NO_WARNINGS
#include<malloc.h>
#include <iostream>
using namespace std;
#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,该栈预定义大小为STACK_INIT_SIZE
// 请补全代码
S.base = new SElemType[STACK_INIT_SIZE];
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
Status Push(SqStack& S, SElemType e)
{
// 在栈S中插入元素e为新的栈顶元素
if (S.stacksize <= S.top - S.base)
{
S.base = (SElemType*)realloc(S.base,sizeof(SElemType) * (S.stacksize + STACKINCREMENT));
if (S.base == NULL)return ERROR;
else
{
S.top = S.base + S.stacksize;
S.stacksize+=STACKINCREMENT;
S.top++;
*S.top = e;
}
}
else
{
S.top++;
*S.top = e;
}
return OK;
}
Status StackTraverse(SqStack S) // 这个代码的栈比较特殊:第一格是空的,top指向最后一个元素
{
// 从栈顶到栈底依次输出栈中的每个元素
SElemType* p = S.top;
if (S.base==S.top)printf("The Stack is Empty!");
else
{
while (p!=S.base)
{
printf("%d", *p--);
}
}
printf("\n");
return OK;
}
int main()
{
struct SqStack A;
InitStack(A);
int n;
cin >> n;
while (n != 0)
{
Push(A,n % 8);
n /= 8;
}
StackTraverse(A);
return 0;
}
// 解法二:c++数组简单模拟
#include <iostream>
using namespace std;
int a[100];
int main()
{
int n;
cin>>n;
int idx=0;
while(n)
{
a[idx++]=n%8;
n/=8;
}
for(int i=idx-1;i>=0;i--)//倒序输出
cout<<a[i];
return 0;
}
# include <stdio.h>
int main ( )
{
int n;
scanf ( "%d" , & n) ;
printf ( "%o" , n) ;
return 0 ;
}
8586 括号匹配检验
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 SElemType[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.base==S.top)
return OK;
else return ERROR;
}
Status Push(SqStack &S,SElemType e)
{
if(S.top-S.base==S.stacksize)
{
S.base=(SElemType*)realloc(S.base,S.stacksize+STACKINCREMENT);
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)
{
if(S.top==S.base)
return ERROR;
S.top--;
e=*S.top;//e是已经被弹出的元素(因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(ERROR);
}
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();
}
8588 表达式求值
8587 行编辑程序
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= new SElemType[STACK_INIT_SIZE];
if(!S.base)
return ERROR;
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return OK;
}
Status StackEmpty(SqStack S)
{
// 若栈S为空栈,则返回TRUE,否则返回FALSE
if(S.base==S.top)
return ERROR;
else return OK;
}
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为新的栈顶元素
if(S.top-S.base==S.stacksize)
{
S.base=(SElemType*)realloc(S.base,S.stacksize+STACKINCREMENT);
if(!S.base)
return ERROR;
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
} //如果空间不够增加存储空间
//本操作不用也行,栈满返回ERROR就行了(毕竟OJ数据比较水不会给到满栈情况
*S.top++=e;
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(); //这个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();
}
8588 表达式求值
// 符号优先关系实在是太多了,懒得写。
18938 汉诺塔问题
#include<malloc.h>
#include<stdio.h>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
void moves(int n,char a,char b,char c)
{
//a,b,c分别为1,2,3柱
//函数含义:利用空的3柱,将盘子塔从1柱移动到目标柱2(中间的字符应该是目标柱,左边的柱子为盘子塔柱)
if(n==1)
{
cout<<a<<"->"<<n<<"->"<<b<<endl;
return;
}
moves(n-1,a,c,b);
//第一步:将1柱除最底盘外的盘子塔移到非目标柱3上
//此时1柱上的盘子塔塔目标3,原目标塔是2,递归时把2交换成3就行
cout<<a<<"->"<<n<<"->"<<b<<endl; //将1柱剩下的盘子n移动到空着的2(注意此时这个盘子是不算盘子塔的一部分的)
moves(n-1,b,c,a);
//最后将已经移动到3柱的盘子塔移动到目标柱2上
//理论上的写法是(3,2,1),因为需要实现的是3->2,根据函数含义,3应该在最左边,2应该在中间,充当目标柱
//但注意此时的3(c)柱已经和2柱(b)交换,因此改写成(2,3,1)
}
int main()
{
int n;
char a,b,c;
cin>>n>>a>>b>>c;
moves(n,a,b,c);
return 0;
}
// 感觉有点难理解,一个很简单的方法,n=1和n=2的情况都是很好推断的
// 记住大概格式,考场直接参考n=1或n=2面向答案编程就行,abc一共就六种搭配总能试出正确写法
8590 队列的应用——银行客户平均等待时间
// 解法一:妈的我不知道这题为什么需要解法一这个数据结构解法又耗空间又耗人力的
// (忍气吞声地写了.jpg
#include<malloc.h>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int QElemType;
#define MAXQSIZE 100 // 最大队列长度(对于循环队列,最大队列长度要减1)
using namespace std;
typedef struct
{
QElemType *base; // 初始化的动态分配存储空间
int front; // 头指针,若队列不空,指向队列头元素
int rear; // 尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue;
Status InitQueue(SqQueue &Q)
{
//构造一个空队列,预定义大小为MAXQSIZE
Q.base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
Q.front=Q.rear=0;
return OK;
}
Status EnQueue(SqQueue &Q,QElemType e)
{
//插入新元素e至队尾
if((Q.rear+1)%MAXQSIZE==Q.front)
return ERROR;
Q.base[Q.rear]=e;
Q.rear=(Q.rear+1)%MAXQSIZE;
return OK;
}
Status GetHead(SqQueue Q,QElemType &e)
{
//若队列不空, 则删除Q的队头元素, 用e返回其值, 并返回OK; 否则返回ERROR
if(Q.rear==Q.front)
return ERROR;
e=Q.base[Q.front];
return OK;
}
Status QueueLength(SqQueue Q)
{
//返回队列的元素个数
return abs(Q.front-Q.rear);
}
double solve(SqQueue Q)
{
int i;
double total=0;
i=Q.front;
while(i!=Q.rear)
{
total+=Q.base[i];
i++;
}
return total;
}
int main()
{
double res=0;
int leave=0;
int stay=0;
SqQueue Q;
InitQueue(Q);
int n;
cin>>n;
int a,b;
EnQueue(Q,0);
cin>>a>>b;
leave=a+b;
for(int i=0; i<n-1; i++)
{
cin>>a>>b;
stay=leave-a;
if(stay<0)//等待时间小于0
{
stay=0;
leave=a+b;
}
else
{
leave+=b;
}
EnQueue(Q,stay);
}
res=solve(Q)/(n);
printf("%.2f",res);
return 0;
}
// 解法二:c++模拟,甚至不需要数组
#include<iostream>
using namespace std;
int main()
{
double res=0;
int leave=0,stay=0;
int n,a,b;
cin>>n;
cin>>a>>b;
leave=a+b;
for(int i=0; i<n-1; i++)
{
cin>>a>>b;
stay=leave-a;
if(stay<0)//等待时间小于0
{
stay=0;
leave=a+b;
}
else
{
leave+=b;
}
res+=stay;
}
res/=n;
printf("%.2f",res);
return 0;
}
18937 阿克曼(Ackmann)函数
#include<iostream>
#include<algorithm>
using namespace std;
int akm(int m,int n)
{
//cout<<m<<" "<<n<<endl;
if(m==0)
return n+1;
else if(m>0&&n==0)
return akm(m-1,1);
else if(m>0&&n>0)
return akm(m-1,akm(m,n-1));
}
int main()
{
int m,n;
cin>>m>>n;
cout<<akm(m,n);
return 0;
} //直接递归
实验三
8591 计算next值
#include "stdio.h"
#include "stdlib.h"
#define MAXSTRLEN 255 // 用户可在255以内定义最大串长
typedef unsigned char SString[MAXSTRLEN+1]; // 0号单元存放串的长度
// hd说不管是next数组还是匹配数组都是01开头
// kmp板子和书上的可能有区别(如果按照书上的做法的话确实是这样)
void get_next(SString T,int next[])
{
// 求模式串T的next函数值并存入数组next
int i=1,j=0; // i在主串上移动,j在next数组上移动
next[1]=0;
while(i<T[0])
{
if(j==0||T[i]==T[j]) //第一次写没写j==0一直卡住无法输出
{
j++,i++;
next[i]=j;
}
else
j=next[j]; // 回跳
}
}
int main()
{
int next[MAXSTRLEN]; //next数组
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");
}
}
8592 KMP算法
#include "stdio.h"
#include "stdlib.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
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 Index_KMP(SString S,SString T,int pos)
{
// 算法4.6
// 利用模式串T的next函数求T在主串S中第pos个字符之后的位置
// KMP算法
int next[255];
get_next(T,next);
pos=1;
int i=pos,j=1;
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,pos);
printf("%d\n",pos);
}
}
18722 稀疏矩阵的运算
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
struct node
{
int x,y,s;
bool operator < (const node &c) const//重载运算符
{
if(y==c.y)return x<c.x;
else return y<c.y;
}
}nodes[10005];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n,m,k;
cin>>n>>m>>k;
for(int i=0;i<k;i++)
cin>>nodes[i].x>>nodes[i].y>>nodes[i].s;
sort(nodes,nodes+k);
for(int i=0;i<k;i++)
cout<<nodes[i].y<<" "<<nodes[i].x<<" "<<nodes[i].s<<endl;
return 0;
}
18769 不完整的排序
#include<iostream>
#include<algorithm>
using namespace std;
int a[100100];
void solve()
{
int n;
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<n)
{
if(a[i]>=0)
break;
i++;
}
while(a[j]>0&&j>=0)
{
if(a[j]<=0)
break;
j--;
}
if(i<j)
swap(a[i],a[j]);
}
for(i=0; i<n; i++)
cout<<a[i]<<" ";
cout<<endl;
}
int main()
{
int t;
cin>>t;
while(t--)
solve();
return 0;
} //直接按题目要求模拟就行了,很简单的
实验四
8606 二叉树的构建及遍历操作
#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) //递归要有终止条件
{
// 前序遍历二叉树T的递归算法
if(T)
{
printf("%c",T->data);
PreOrderTraverse(T->lchild);
PreOrderTraverse(T->rchild);
}
return OK;
} // PreOrderTraverse
Status InOrderTraverse( BiTree T)
{
// 中序遍历二叉树T的递归算法
if(T)
{
InOrderTraverse(T->lchild);
printf("%c",T->data);
InOrderTraverse(T->rchild);
}
return OK;
} // InOrderTraverse
Status PostOrderTraverse( BiTree T)
{
// 后序遍历二叉树T的递归算法
if(T)
{
PostOrderTraverse(T->lchild);
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);
printf("\n");
return 0;
}//main
17121 求二叉树各种节点数
#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
int count_0=0, count_1=0, count_2=0; //记录度为0、1、2的节点数
void CountTree(BiTree T)
{
//统计度数
if(T)
{
if(T->lchild&&T->rchild)
count_2++;
else if(T->lchild||T->rchild)
count_1++;
else count_0++;
CountTree(T->lchild);
CountTree(T->rchild);
}
return ;
}
int main() //主函数
{
BiTree T;
CreateBiTree(T);
CountTree(T);
printf("%d\n%d\n%d\n",count_2,count_1,count_0);
return 0;
}//main
18924 二叉树的宽度
// 解法一:数据结构(其实一二解法原理差不多,都要使用队列)
#include "stdio.h"
#include "malloc.h"
#include <iostream>
#include <queue>
#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;
BiTree node[55];
Status Count_wide()
{
int res=1; //初始化res=1(根节点),防止输入n=1的特殊情况
std::queue<int>q;
q.push(1);
int tem=q.size();
while(!q.empty())
{
for(int i=1; i<=tem; i++)
{
int k=q.front();
q.pop();
if(node[k]->lchild)
{
BiTree temp=node[k]->lchild;
q.push(temp->data);
}
if(node[k]->rchild)
{
BiTree temp=node[k]->rchild;
q.push(temp->data);
}
}
tem=q.size();
res=std::max(res,tem);
}
return res;
}
int main() //主函数
{
int n,a,b;
std::cin>>n;
for(int i=1; i<=50; i++)
{
node[i] = (BiTNode*)malloc(sizeof(BiTNode)); // 为每个节点分配内存
// 注意写分配内存!因为漏写卡了很久
node[i]->data=i;
node[i]->lchild=NULL;
node[i]->rchild=NULL;
}
for(int i=1; i<n; i++)
{
std::cin>>a>>b;
if(!node[a]->lchild)
node[a]->lchild=node[b];
else node[a]->rchild=node[b];
}
std::cout<<Count_wide()<<std::endl;
return 0;
}//main
// 解法二:c++数组pair模拟树结点
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
typedef pair<int,int> PII;
PII a[55];
int main() {
int n,x,y,ans=0;
cin>>n;
for(int i=1; i<=n-1; ++i) {
cin>>x>>y;
if(!a[x].first) {
a[x].first=y;
} else {
a[x].second=y;
}
}
queue<int>q;
q.push(1);
while(!q.empty()) {
int len=q.size();
ans=max(ans,len);
for(int i=1; i<=len; ++i) {
int t=q.front();
q.pop();
if(a[t].first) {
q.push(a[t].first);
}
if(a[t].second) {
q.push(a[t].second);
}
}
}
cout<<ans;
return 0;
}
// 解法三:递归求宽度
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef pair<int,int> PII;
PII a[55];
int layers[55];
void width(int node,int layer)
{
layers[layer]++;//遍历到每个点,改层的结点数加一
if(a[node].first)
width(a[node].first,layer+1);
if(a[node].second)
width(a[node].second,layer+1);
}
int main()
{
int n,x,y,ans=0;
cin>>n;
for(int i=1; i<=n-1; ++i)
{
cin>>x>>y;
if(!a[x].first)
a[x].first=y;
else a[x].second=y;
}//先建树
memset(layers,0,sizeof layers);//先将每一层的结点数清零
width(1,1);//递归求宽度
int res=0;
for(int i=1; i<=n; i++) //遍历每一层,二叉树宽度为最多结点层的结点数
res=max(res,layers[i]);
cout<<res<<endl;
return 0;
}
18724 二叉树的遍历运算
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 60;
string s1,s2;
void solve(int prel,int prer,int midl,int midr)
{
char c=s1[prel];
int i;
if(prel>prer||midl>midr)
return; //递归终止条件
for(i=midl; i<=midr; i++)
if(s2[i]==c)
break;
//左子树长度是i-midl,右子树是midr-i
solve(prel+1,prel+i-midl,midl,i-1);
solve(prel+i-midl+1,prer,i+1,midr);
cout<<c;
}
int main()
{
cin>>s1>>s2; //先序遍历和中序遍历
int prel=s1.size(),midl=s2.size();
solve(0,prel-1,0,midl-1);
return 0;
}
18923 二叉树的直径
#include<iostream>
#include<algorithm>
using namespace std;
typedef pair<int,int> PII;
PII a[55];
int ans;
int dfs(int n){
if(!n){
return 0;
}else{
int l=dfs(a[n].first),r=dfs(a[n].second);
int len=max(l,r)+1;
ans=max(ans,l+r);
return len;
}
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n-1;++i){
int x,y;
cin>>x>>y;
if(!a[x].first){
a[x].first=y;
}else{
a[x].second=y;
}
}
dfs(1);
cout<<ans;
return 0;
}
8609 哈夫曼树
#include "stdio.h"
#include "string.h"
#include "iostream"
using namespace std;
typedef struct
{
unsigned int weight;
unsigned int parent,lchild,rchild;
} HTNode,*HuffmanTree;
typedef char **HuffmanCode;
void select(HuffmanTree &HT, int n, int &s1, int &s2)
{
//在HT[1..n]中选择parent为0且weight最小的两个结点, 其序号分别为s1(最小)和s2(次小)。
int a=1e9,b=1e9;
for(int i=1; i<=n; i++)
{
if(HT[i].weight<a&&HT[i].parent==0) //要区分清楚结点权值和结点序号
{
s2=s1;
s1=i;
b=a;
a=HT[i].weight;
}
else if(HT[i].weight<b&&HT[i].parent==0)
{
s2=i;
b=HT[i].weight;
}
}
}
void createHuffmanTree(HuffmanTree &HT, int n)
{
//构造哈夫曼树HT
int i, m, s1, s2;
if (n<=1) return;
m = 2 * n - 1;
HT = new HTNode[m+1]; // 0号单元未用
for (i=1; i<=m; i++) //初始化HT数组
{
HT[i].parent=0;
HT[i].lchild=0;
HT[i].rchild=0;
}
for (i=1; i<=n; i++) //输入n个数
cin>>HT[i].weight;
for (i=n+1; i<=m; i++) // 建哈夫曼树
{
//在HT[1..i-1]中选择parent为0且weight最小的两个结点, 其序号分别为s1(最小)和s2(次小)
select(HT,i-1,s1,s2); //寻找weight最小的两个结点,传参给s1和s2
HT[i].weight=HT[s1].weight+HT[s2].weight;
HT[i].lchild=s1; //左小右大
HT[i].rchild=s2;
HT[s1].parent=i;
HT[s2].parent=i;
}
}
void createHuffmanCode(HuffmanTree HT,HuffmanCode &HC,int n)
{
//--- 从叶子到根逆向求每个字符的哈夫曼编码 ---
char *cd = new char[n]; // 分配求编码的工作空间
cd[n-1] = '\0'; // 编码结束符。
int i,c,f,start;
for (i=1; i<=n; ++i)
{
start = n-1;
c=i, f=HT[i].parent;
while(f)// 从叶子到根逆向求编码
{
--start;
if (HT[f].lchild==c) cd[start] = '0';
else cd[start] = '1';
c=f,f=HT[f].parent;
}
HC[i] = new char[n-start]; // 为第i个字符编码分配空间
strcpy(HC[i], &cd[start]); // 从cd复制编码(串)到HC
}
}
int main()
{
int i,n;
int *w;
HuffmanTree HT;
HuffmanCode HC;
scanf("%d",&n); //权值个数
HC=new char*[n+1]; //0空间未用
createHuffmanTree(HT,n);
createHuffmanCode(HT,HC,n);
for (i = 1; i<=n; i++)
printf("%s\n",HC[i]); //输出哈夫曼编码
}
实验五
8610 顺序查找
#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=1; i<=ST.length; 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 二分查找
// 解法一:手撕二分查找
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n,key;
cin>>n;
int a[n+10];
for(int i=0; i<n; i++)
cin>>a[i];
cin>>key; //输入关键字
int l=0,r=n-1,mid;
while(l<=r)
{
//注意本题不会出现重复元素
mid=(l+r)>>1;
if(key>a[mid])l=mid+1;
else if(key<a[mid])r=mid-1;
else
{
cout<<"The element position is "<<mid<<"."<<endl;
return 0;
}
}
cout<<"The element is not exist."<<endl;
return 0;
}
// 解法二:c++标准库函数lower_bound()快速实现
#include <iostream>
#include <algorithm>
using namespace std;
//lower_bound 用于二分查找区间内第一个 大于等于某值(>= x) 的迭代器位置
//upper_bound 用于二分查找区间内第一个 大于某值(> x) 的迭代器位置
int main()
{
int n,key;
cin>>n;
int a[n+10];
for(int i=0; i<n; i++)
cin>>a[i];
cin>>key; //输入关键字
int* pos=lower_bound(a,a+n,key);
// auto pos=lower_bound(a,a+n,key);
// int* 可以改成auto,迭代器为指针类型,数值为内存位置,因此要减去a(数组首内存)
if((pos-a)==n&&key!=a[n-1]) // 如果没找到,会返回数组最后一个地址
cout<<"The element is not exist."<<endl;
else cout<<"The element position is "<<pos-a<<"."<<endl;
return 0;
}
8622 哈希查找
#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 (3*K)%length;
}
void collision(int *p) /*线性探测再散列 */
{
/* 开放定址法处理冲突 */
*p=(*p+1)%length; //最开始忘记取mod了
}
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 直接插入排序
// 本题用数组写法跟用顺序表没什么大区别,就直接对应书本写了
#include <iostream>
#include <algorithm>
#include <cstdio>
#define MAXSIZE 100
using namespace std;
typedef int KeyType;
typedef struct
{
KeyType r[MAXSIZE+1]; //顺序表单元,r[0]闲置
int length; //顺序表长度
} SqList; //顺序表
//数据结构课本算法8.1
void Insert_sort(SqList &L)
{
int i,j,k;
for(i=2; i<=L.length; i++)
{
if(L.r[i]<L.r[i-1]) //此时的r[i]需插入i前面已经排序好的表中
{
L.r[0]=L.r[i];
//稍微改动了一下课本,方便理解。直接照抄课本P230算法8.1也能过,去掉.key就行
for(j=i-1; j>0; j--)
{
L.r[j+1]=L.r[j];
if(L.r[j]<=L.r[0])
break;
}
L.r[j+1]=L.r[0];
}
for(k=1; k<=L.length; k++) //每一次插入输出一次
cout<<L.r[k]<<" ";
cout<<endl;
}
}
int main()
{
SqList L;
cin>>L.length;
for(int i=1; i<=L.length; i++)
cin>>L.r[i];
Insert_sort(L);
return 0;
}
8639 折半插入排序
// 其实这题直接拿上一题的代码交就能通过QWQ
#include <iostream>
#include <algorithm>
#include <cstdio>
#define MAXSIZE 100
using namespace std;
typedef int KeyType;
typedef struct
{
KeyType r[MAXSIZE+1]; //顺序表单元,r[0]闲置
int length; //顺序表长度
} SqList; //顺序表
//数据结构课本算法8.2
void Binary_Insert_sort(SqList &L)
{
int i,j,k;
for(i=2; i<=L.length; i++)
{
L.r[0]=L.r[i];
int low=1,high=i-1;
while(low<=high) //二分寻找插入位置
{
int mid=(low+high)/2;
if(L.r[0]<L.r[mid])high=mid-1;
else low=mid+1;
}
for(j=i-1; j>=high+1; j--)
L.r[j+1]=L.r[j];
L.r[high+1]=L.r[0];
for(k=1; k<=L.length; k++) //每次插入输出当前顺序表
cout<<L.r[k]<<" ";
cout<<endl;
}
}
int main()
{
SqList L;
cin>>L.length;
for(int i=1; i<=L.length; i++)
cin>>L.r[i];
Binary_Insert_sort(L);
return 0;
}
8640 希尔(shell)排序
#include <iostream>
#include <algorithm>
#include <cstdio>
#define MAXSIZE 100
using namespace std;
typedef int KeyType;
typedef struct
{
KeyType r[MAXSIZE+1]; //顺序表单元,r[0]闲置
int length; //顺序表长度
} SqList; //顺序表
//数据结构课本算法8.3
void ShallInsert(SqList &L)
{
int dk=L.length/2; //设置增量d同等于课本的dk
while(dk)
{
int i,j;
for(i=dk+1; i<=L.length; i++)
{
if(L.r[i]<L.r[i-dk])
{
L.r[0]=L.r[i];
for(j=i-dk; j>0&&L.r[0]<L.r[j]; j-=dk) //注意别忘记写j>0!!
L.r[j+dk]=L.r[j];
L.r[j+dk]=L.r[0];
}
}
for(int k=1; k<=L.length; k++) //每次插入输出当前顺序表
cout<<L.r[k]<<" ";
cout<<endl;
dk/=2;
}
}
int main()
{
SqList L;
cin>>L.length;
for(int i=1; i<=L.length; i++)
cin>>L.r[i];
ShallInsert(L);
return 0;
}
8641 冒泡排序
#include <iostream>
#include <algorithm>
#include <cstdio>
#define MAXSIZE 100
using namespace std;
typedef int KeyType;
typedef struct
{
KeyType r[MAXSIZE+1]; //顺序表单元,r[0]闲置
int length; //顺序表长度
} SqList; //顺序表
//数据结构课本算法8.4
void ShallInsert(SqList &L)
{
int m=L.length-1,flag=1;//flag用于标记一趟排序是否发生交换
while((m>0)&&(flag==1))
{
flag=0;//flag初始化为0
for(int j=1; j<=m; j++)
{
if(L.r[j]>L.r[j+1])
{
flag=1;
swap(L.r[j],L.r[j+1]);//交换前后记录
}
}
m--;
for(int i=1; i<=L.length; i++) //输出
cout<<L.r[i]<<" ";
cout<<endl;
}
}
int main()
{
SqList L;
cin>>L.length;
for(int i=1; i<=L.length; i++)
cin>>L.r[i];
ShallInsert(L);
return 0;
}
8642 快速排序
//数据结构课本给出的写法
#include <iostream>
#include <algorithm>
#include <cstdio>
#define MAXSIZE 100
using namespace std;
typedef int KeyType;
typedef struct
{
KeyType r[MAXSIZE+1]; //顺序表单元,r[0]闲置
int length; //顺序表长度
} SqList; //顺序表
//数据结构课本算法8.5(P237)
int Partition(SqList &L,int low,int high)
{
L.r[0]=L.r[low];//以表中第一个数为枢纽
int pivotkey=L.r[low];//记录关键字;
while(low<high)//交替向中间寻找
{
while(low<high&&L.r[high]>=pivotkey)
high--;
L.r[low]=L.r[high];
while(low<high&&L.r[low]<=pivotkey)
low++;
L.r[high]=L.r[low];
}
L.r[low]=L.r[0];
return low;//返回枢纽所在位置
}
void Quick_sort(SqList &L,int low,int high)
{
if(low<high)
{
int pivotloc=Partition(L,low,high);
for(int i=1; i<=L.length; i++) //输出
cout<<L.r[i]<<" ";
cout<<endl;
//递归实现快排
Quick_sort(L,low,pivotloc-1);
Quick_sort(L,pivotloc+1,high);
}
}
int main()
{
SqList L;
cin>>L.length;
for(int i=1; i<=L.length; i++)
cin>>L.r[i];
Quick_sort(L,1,L.length);
return 0;
}
//简化了一下
#include <iostream>
using namespace std;
int n;
int a[100];
void quick_sort(int high, int low)
{
int i = high, j = low;
int t = a[i]; // 将基准数保存在t中
if (i < j) // 这里的if else是为了防止有特殊情况,其实感觉有后面的while就够了
{
while (i < j) // 循环交换实现快排
{
while (i < j && a[j] >= t)
j--;
if (i < j)
{
a[i] = a[j];
i++; // 数字改变后指针立刻后移,防止陷入死循环
//OJ给的数据没有卡这个,这句i++和后面的j--去掉也不会死循环,能通过
}
while (i < j && a[i] <= t) // 如果a[i]一直不大于t的话,最后i=j循环终结
i++;
if (i < j)
{
a[j] = a[i];
j--;
} // 确保进入两个while循环的时候i<j,两个循环停止时i=j
}
}
else
return; // 设置递归终止条件
// 最后i、j指针重合的地方就是基准数
a[i] = t; // 将基准数放置在正确的位置
for (int k = 1; k <= n; k++)
cout << a[k] << ' ';
cout << endl;
quick_sort(high, i - 1);
quick_sort(i + 1, low);
return;
}
int main()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> a[i];
quick_sort(1, n);
return 0;
}
8643 简单选择排序
#include <iostream>
#include <algorithm>
#include <cstdio>
#define MAXSIZE 100
using namespace std;
typedef int KeyType;
typedef struct
{
KeyType r[MAXSIZE+1]; //顺序表单元,r[0]闲置
int length; //顺序表长度
} SqList; //顺序表
//数据结构课本算法8.6简单选择排序
int Selectsort(SqList &L)
{
for(int i=1; i<L.length; i++)
{
int k=i;
for(int j=i+1; j<=L.length; j++)//找到最小值对应的数组下标
if(L.r[j]<L.r[k])k=j;
if(k!=i) //如果不是i则交换
swap(L.r[i],L.r[k]);
for(int g=1; g<=L.length; g++) //输出
cout<<L.r[g]<<" ";
cout<<endl;
}
}
int main()
{
SqList L;
cin>>L.length;
for(int i=1; i<=L.length; i++)
cin>>L.r[i];
Selectsort(L);
return 0;
}
8644 堆排序
#include <iostream>
#include <algorithm>
#include <cstdio>
#define MAXSIZE 100
using namespace std;
typedef int KeyType;
typedef struct
{
KeyType r[MAXSIZE+1]; //顺序表单元,r[0]闲置
int length; //顺序表长度
} SqList; //顺序表
//数据结构课本算法8.7:筛选法调整堆
void HeapAdjust(SqList &L,int s,int m)
{
//把堆调整为以r[s]为根的大根堆
int rc=L.r[s];//此时标记为根结点(r[s]其实就是r[1])
for(int j=2*s; j<=m; j*=2)//寻找rc应该放的位置
{
if(j<m&&L.r[j]<L.r[j+1])
j++;//j为值较大的孩子坐标
if(rc>=L.r[j])break;//如果此时父结点rc大,大根堆里rc最大
//否则将根结点改为该值
L.r[s]=L.r[j];
s=j;
}
L.r[s]=rc;//把rc放在应放的地方(保证大根堆)
}
//数据结构课本算法8.8:初建堆
//大根堆:父结点大于子结点(只能保证根结点是最大值)
void CreatHeap(SqList &L)
{
int n=L.length;
//这个n/2非常之巧妙(和难理解),如果理解不了直接写i=n就行,相当于一个元素一个元素调整大根堆
//由于序号大于n/2的结点都必定是叶子,因此n/2-n范围内都不是叶子,调整过程中可以遍历完非每一层
for(int i=n/2; i>0; i--)
HeapAdjust(L,i,n);
}
//数据结构课本算法8.9:堆排序
int main()
{
SqList L;
cin>>L.length;
for(int i=1; i<=L.length; i++)//输出顺序表
cin>>L.r[i];
CreatHeap(L); //把无序列表建立为大根堆
for(int i=L.length; i>=1; i--)
{
for(int g=1; g<=L.length; g++) //输出
cout<<L.r[g]<<" ";
cout<<endl;
//交换:将此时的根结点(最大值)放到列尾,一个个放,直到队列有序
swap(L.r[1],L.r[i]);
HeapAdjust(L,1,i-1); //重新调整为大根堆
}
return 0;
}
8645 归并排序(非递归算法)
//何必呢……不用递归能给你我带来什么……课本都是用的递归啊……
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin>>n;
int a[n+10];
for (int i=0; i<n; i++)
cin>>a[i];
//归并本质就是一小块一小块排序,模拟一下
int step=2; //最开始是两两排序
while(step<n)//这里不能取等,因为如果n是2的次方的话会重复输出
{
for(int i=0; i<n; i+=step)
sort(a+i,a+min(i+step,n));
step*=2;
for(int g=0; g<n; g++) //输出
cout<<a[g]<<" ";
cout<<endl;
}
sort(a,a+n);
for(int g=0; g<n; g++) //输出
cout<<a[g]<<" ";
cout<<endl;
return 0;
}
8646 基数排序
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <stack>
#include <map>
#include <queue>
#include <cmath>
#include <cstdio>
#include<iomanip>
using namespace std;
const int N = 100000; //N后续使用的时候会根据题目范围修改
const int mod = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
vector<int> d[10];//创建10个向量
int a[10000]= {0};
int pow(int k,int mi)//幂运算
{
int sum=1;
for(int i=0; i<mi; i++)
{
sum*=k;
}
return sum;
}
int weishu(int t)//数的位数
{
int i=0;
while(t)
{
t = t/10;
i++;
}
return i;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int n,i,maxx=0,j,t,z;
cin>>n;
for(int i=1; i<=n; i++)
{
cin>>a[i];
maxx=max(maxx,weishu(a[i]));//找出最大位数
}
for(int i=0; i<maxx; i++)
{
//进行几次基数排序
for(int j=1; j<=n; j++)
d[a[j]/pow(10,i)%10].push_back(a[j]);//将a[]数据压入向量容器中
t = 1;
for(j=0; j<10; j++) //将十个向量容器中的数据重新录入a[]中
{
for(z=0; z<d[j].size(); z++) //单个向量容器中的数据
a[t++] = d[j][z];
d[j].clear();//清除向量
}
for(j=1; j<=n; j++) //输出a[]
cout << setw(maxx) << setfill('0') << a[j] << ' ';
cout << endl;
}
return 0;
}
实验七
8647 实现图的存储结构
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int a[1100][1100];
int main()
{
int n,m;
cin>>n>>m;
memset(a,0,sizeof a);
while(m--)
{
int i,j;
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 图的深度遍历
#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);//相当于调用print
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);//递归调用DFS
}
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");
}
void print(char *i)
{
printf("%s ",i);
}
int main()
{
ALGraph g;
CreateGraph(&g);
DFSTraverse(g,print);
return 1;
}
8649 图的广度遍历
//在深度遍历的基础上修改了一下,记得补上头文件queue
#include"string.h"
#include"malloc.h" /* malloc()等 */
#include"stdio.h" /* EOF(=^Z或F6),NULL */
#include"stdlib.h" /* exit() */
#include"queue"
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 BFS(ALGraph G,int v)
{
std::queue<int> Q;
visited[v]=1;
Q.push(v);
VisitFunc(G.vertices[v].data);
while(!Q.empty())
{
int tem=Q.front();
Q.pop();
for(int w=FirstAdjVex(G,G.vertices[tem].data); w>=0; w=NextAdjVex(G,G.vertices[tem].data,G.vertices[w].data))
{
if(!visited[w])
{
visited[w]=true;
VisitFunc(G.vertices[w].data);//输出
Q.push(w);
}
}
}
}
void BFSTraverse(ALGraph G,void(*Visit)(char*))
{
/* 对图G作深度优先遍历。算法7.4 */
/* 使用全局变量VisitFunc,使BFS不必设函数指针参数 */
/* 访问标志数组初始化 */
/* 对尚未访问的顶点调用BFS */
VisitFunc=Visit;
for(int v=0; v<G.vexnum; v++)//初始化所有未访问结点为false
visited[v]=false;
for(int v=0; v<G.vexnum; v++)
if(!visited[v])BFS(G,v);
printf("\n");
}
void print(char *i)
{
printf("%s ",i);
}
int main()
{
ALGraph g;
CreateGraph(&g);
BFSTraverse(g,print);
return 1;
}
18448 最小生成树(还没做)
18732 最短路问题
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
const int N = 101;
const int inf = 0x3f3f3f3f;
int f[N][N];
int main(void) {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int n, m; std::cin >> n >> m;
memset(f, 0x3f, sizeof(f));
for (int i = 1; i <= n; i += 1)f[i][i] = 0;
for (int i = 1; i <= m; i += 1) {
int a, b, x; std::cin >> a >> b >> x;
f[a][b] = std::min(f[a][b], x);
f[b][a] = std::min(f[b][a], x);
}
for (int k = 1; k <= n; k += 1) {
for (int i = 1; i <= n; i += 1) {
for (int j = 1; j <= n; j += 1) {
f[i][j] = std::min(f[i][j], f[i][k] + f[k][j]);
}
}
}
std::cout << (f[1][n] == inf ? -1 : f[1][n]);
return 0;
}
18734 拓扑排序
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int nelist[25][25];
int main()
{
int n,m;
cin>>n>>m;
memset(nelist,0,sizeof nelist);
while(m--)
{
int a,b;
cin>>a>>b;
nelist[a-1][b-1]=1;
} // 建图
int node[n+10]; // 纪录入度
memset(node,0,sizeof node);
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
if(nelist[i][j])
node[j]++;
int p[n+10]; // 标记是否输出过
memset(p,0,sizeof p);
for(int g=0; g<n; g++)
{
int k;
for(k=0; k<n; k++)
if(node[k]==0&&p[k]==0)
{
cout<<k+1<<" ";
p[k]=1;
break;
}
for(int i=0; i<n; i++)
if(nelist[k][i])
node[i]--;
}
return 0;
}