基础顺序结构(顺序表和链表)
顺序表(sqlist)
结构定义
typedef struct {
ElemType *data;
int length;
}sqlist;
头文件定义
#include<iostream>
using namespace std;
#define MAXSIZE 100
typedef int ElemType;
函数定义
bool initlist(sqlist &L)//创建顺序表
{
bool judge=true;
L.data=new ElemType[MAXSIZE];//为L.dada申请长为MAXSIZE的空间
if(L.data==NULL)//判断是否申请成功
{
cout<<"没有申请到空间"<<endl;
judge=false;//如果没有申请成功,就将judge改为false
return judge;//返回false
}
return judge;
}
void input(sqlist &L,int n)
{
if(n<0||n>MAXSIZE)//进行n的合法性判断,如果N小于0或者超过最大数组长度,输出提醒语句
{
cout<<"想要输入的数据个数不对"<<endl;
}
for(int i=0;i<n;i++)//利用for循环,循环n次输入data的数值
{
cin>>L.data[i];
}
L.length=n;//将sqlist的长度设置为n
cout<<"L.length:"<<L.length<<endl;
}
void showlist(sqlist &L)
{
int i;
for(i=0;i<L.length;i++)//利用length属性,设计for循环遍历数组的每一个值
{
cout<<L.data[i]<<" ";
}
cout<<endl;
cout<<"L.length:"<<L.length<<endl;
}
void deletelist(sqlist &L,int i)
{
if(i>L.length||i<0)//进行数据的合法性检查,如果i大于顺序表的长度或者
//i小于0,输出提醒语句
{
cout<<"找不到这样的第i位哦"<<endl;
}
int j;//设置j找到i的前一位
for(j=i-1;j<L.length;j++)
{
L.data[j]=L.data[j+1];//将j后一位的数值赋给j,原i位被覆盖
}
L.length-=1;//顺序表的长度减一
}
void insertlist(sqlist &L,int j,int e)
{
if(j<0||j>MAXSIZE)//进行数据的合法性检查,如果i大于顺序表的长度或者
//i小于0,输出提醒语句
{
cout<<"插入的位置不对"<<endl;
}
L.length++;//因为要插入一位数,所以提前把顺序表的长度增加一位
int x;
for(x=L.length-1;x>j;x--)//从数组的最后一位开始循环,
//在插入位置i的前一位停止
{
L.data[x]=L.data[x-1];//将x前一位的数据赋值给x的后一位
}
L.data[j]=e;//将的i位的数据置为e;
}
void cleanlist(sqlist &L)
{
L.length=0;//直接将顺序表的长度置为0
}
void destrylist(sqlist &L)
{
delete []L.data;//删除数组空间
L.length=0;//将顺序表的长度置为0
}
void showlength(sqlist L)
{
cout<<"顺序表的长度:"<<L.length<<endl;
}
void serlist(sqlist &L)//逆置顺序表
{
ElemType *q,*p;//设置两个Elemtype类型的指针,以从开始和末尾移动数组元素
ElemType temp;//作为临时变量保存q的数值
q=&L.data[0];//将q指向数组的开头
p=&L.data[L.length-1];//将p指向数组的末尾
while(q<p)//令数组从开头和结尾依次向前前进一位和从后向前一位
{
temp=*q;//让temp先保存原q的值,
*q=*p;//将q的值置为后面的p的值
*p=temp;//q的值赋值为temp保存的原来q的值
q++;//q从原来数组的位置前进一位
p--;//p从原来数组的位置从后向前前进一位
}
}
void deletex (sqlist &L,int x)
{
int i,j;
for(i=0;i<L.length;i++)//遍历完整个数组
{
if(L.data[i]==x)//当发现有数组中有与x相同的元素时
{//将这个位置的数组元素用后一位的元素覆盖
for(j=i;j<L.length;j++)
{
L.data[j]=L.data[j+1];
}
L.length--;//将顺序表的长度减一
i--;//这里是为了将i重新置为相对的开始状态
}
}
}
main函数定义
#include"sqlisthead.h"
#include"sqlistdef.h"
#include"sqlistcpp.h"
int main()
{
int inputbot,insetdata,insetloate,n,i,j,e,x;
sqlist L;
do{
cout<<endl;
cout<<"\t按0开始初始化顺序表"<<endl;
cout<<"\t按1开始输入n位顺序表数据"<<endl;
cout<<"\t按2开始查看顺序表数据"<<endl;
cout<<"\t按3开始删除指定的i位的数据"<<endl;
cout<<"\t按4开始向插入第i位后插入数据e"<<endl;
cout<<"\t按5开始清除线性表"<<endl;
cout<<"\t按6开始销毁线性表"<<endl;
cout<<"\t按7开始取得顺序表的长度"<<endl;
cout<<"\t按8将顺序表逆转"<<endl;
cout<<"\t按9删除顺序表中的所有X元素"<<endl;
cout<<"\t按-1退出操作"<<endl;
cin>>inputbot;
if(inputbot==0)
{
initlist(L);
cout<<L.data;
}
else if(inputbot==1)
{
cout<<"请输入顺序表的个数"<<endl;
cin>>n;
input(L,n);
}
else if(inputbot==2)
{
showlist(L);
}
else if(inputbot==3)
{
cin>>i;
deletelist(L,i);
}
else if(inputbot==4)
{
cin>>j;
cin>>e;
insertlist(L,j,e);
}
else if(inputbot==5)
{
cleanlist(L);
}
else if(inputbot==6)
{
destrylist(L);
}
else if(inputbot==7)
{
showlength(L);
}
else if(inputbot==8)
{
serlist(L);
}
else if(inputbot==9)
{
cout<<"请输入想要删除的元素X数值"<<endl;
cin>>x;
deletex(L,x);
}
}while(inputbot!=-1);
}
PS:main函数的条件判断用switch…case…结构更好,效率更高
运行截图:
带头结点的单链表
头文件定义
#include<iostream>
using namespace std;
typedef int Elemtype;
结构体定义
typedef struct LNode{
Elemtype data;
struct LNode *next;
}LNode;
typedef LNode* linklist;
函数体定义:
void initlist(linklist L)
{
L=new LNode;//新建一个节点空间
if(L==NULL)
{
cout<<"分配内存失败"<<endl;//提示性语句
}
L->next=NULL;//将节点的next置为NULL
}
void showlinklist(linklist L)
{
cout<<"L=>";
LNode* p=L;//将P和L的头节点链接
while(p->next!=NULL)//当p未到链表结尾处时一直循环
{
p=p->next;//p走向下一个节点
cout<<p->data<<"=>";
}
cout<<"NULL"<<endl;
}
void insertlist(linklist &L,int i,Elemtype e)
{
int count=0;
LNode* p=L;
while(p->next!=NULL&&count<i-1)//向下循环直至到达i节点的前一个节点
{
p=p->next;
count++;
}
if(!p||(count>i-1))//合法性判断,当i>链表的长度或者i<0时,输出提示语句
{
cout<<"想插入的位置i不合法"<<endl;
}
LNode* s;
s=new LNode;//申请一个新的空间
s->data=e;//赋值
s->next=p->next;//将原来p链接的节点转而链接到s后面
p->next=s;//将节点s链接到p的后面
}
void deletelist(linklist &L,int x)
{
LNode* p=L;
int j=0;
while((p->next)&&(j<x-1))//当p不为结尾NULL并且没有到达x节点时
//p不断后移,j++
{
p=p->next;
j++;
}
if(p==NULL||(j>x-1))//合法性检查
{
cout<<"想删除的位置x不合法"<<endl;
}
LNode* q=p->next;//设置q保存p后面链接的地址
p->next=q->next;//让p指向原来p的后两位
delete q;//释放q,即删除原来的节点p
}
void getelem(linklist L,int i)
{
Elemtype e;
linklist p=L->next;//将p指向第一个节点
int j=1;
while(p&&j<i)//遍历链表,直至p找到i的位置
{
p=p->next;
j++;
}
if(p==NULL||j>i)//合法性检查
{
cout<<"想取值的位置y不合法"<<endl;
}
e=p->data;//将p的数据域的部分通过e带出
cout<<"第y个位置的值为"<<e<<endl;
}
void createlist(linklist &L,int n)
{
//通过尾插法创建数组,先创建一个空节点,指针域置为NULL,r指向L
LNode* r;
LNode* p;
L=new LNode;
L->next=NULL;
r=L;
for(int i=0;i<n;i++)
{
p=new LNode;//新建一个新节点
cin>>p->data;
p->next=NULL;//将p的指针域置为NULL
r->next=p;//将新节点p插入尾节点r之后
r=p;//p指向新的尾节点
}
}
void deleteall(linklist &L)
{
linklist q;
while(L)//当链表没有循环到末尾时
{
q=L->next;//q承载L的后继指针
delete(L);//清空L
L=q;//L重新指向q承载的指针
}
}
int showlength(linklist L)
{
int countx=0;
linklist p;
p=L->next;
while(p)
{
countx++;
p=p->next;
}
return countx;
}
void findmaxmin(linklist L,int flag)
{
linklist p;
Elemtype temp;
p=L;
p=p->next;
temp=p->data;
if(flag==1)
{
while(p)
{
if((p->data)>temp)
{
temp=p->data;
}
p=p->next;
}
cout<<"最大数是"<<temp<<endl;
}
else {
while(p)
{
if(p->data<temp)
{
temp=p->data;
}
p=p->next;
}
cout<<"最小数是"<<temp<<endl;
}
}
void reverselist(linklist &head)
{
linklist p,q;
p=head->next;
head->next=NULL;//首先我们让链表为空,断开(head->next=NULL),
//在这时我们只需要将p和q分别用头插法的方式链接起来,链表的逆序也就完成了。
while(p!=NULL)
{
q=p;
p=p->next;//p向后遍历
q->next=head->next;//利用头插法
head->next=q;//将q连接到head后面
}
}
main函数定义
int main()
{
linklist L;
int n,y,x,i,flag;
Elemtype e;
int input;
cout<<"\t按1初始化链表"<<endl;
cout<<"\t按2向链表输入N个数据"<<endl;
cout<<"\t按3向第i个位置插入数据e"<<endl;
cout<<"\t按4删除第x位置的数据"<<endl;
cout<<"\t按5显示链表的y个位置的数据大小"<<endl;
cout<<"\t按6展示链表"<<endl;
cout<<"\t按7销毁链表"<<endl;
cout<<"\t按8求得链表的长度"<<endl;
cout<<"\t按9查询链表中的最大最小值"<<endl;
cout<<"\t按10进行链表的逆置"<<endl;
cin>>input;
do{
if(input==1)
{
initlist(L);
}
else if(input==2)
{
cout<<"确认的数据的个数"<<endl;
cin>>n;
createlist(L,n);
}
else if(input==3)
{
cout<<"请输入i"<<endl;
cin>>i;
cout<<"请输入e"<<endl;
cin>>e;
insertlist(L,i,e);
}
else if(input==4)
{
cout<<"请输入x"<<endl;
deletelist(L,x);
}
else if(input==5)
{
cout<<"请输入y"<<endl;
cin>>y;
getelem(L,y);
}
else if(input==6)
{
showlinklist(L);
}
else if(input==7)
{
deleteall(L);
}
else if(input==8)
{
int length= showlength(L);
cout<<"链表的长度为"<<length<<endl;
}
else if(input==9)
{
cout<<"请输入想要找到是最大数还是最小数"<<endl;
cout<<"找最大数输入1,找最小数输入2"<<endl;
cin>>flag;
findmaxmin(L,flag);
}
else if(input==10)
{
reverselist(L);
}
cout<<"\t按1初始化链表"<<endl;
cout<<"\t按2向链表输入N个数据"<<endl;
cout<<"\t按3向第i个位置插入数据e"<<endl;
cout<<"\t按4删除第x位置的数据"<<endl;
cout<<"\t按5显示链表的y个位置的数据大小"<<endl;
cout<<"\t按6展示链表"<<endl;
cout<<"\t按7销毁链表"<<endl;
cout<<"\t按8求得链表的长度"<<endl;
cout<<"\t按9查询链表中的最大最小值"<<endl;
cout<<"\t按10进行链表的逆置"<<endl;
cout<<"\t按-1退出操作"<<endl;
cin>>input;
}while(input!=-1);
}
运行截图:
栈
顺序栈
头文件定义
#include<iostream>
#define maxsize 100
using namespace std;
typedef int Selemtype;
结构定义
typedef struct {//顺序栈的结构体定义
Selemtype *base;//栈的尾指针
Selemtype *top;//栈的头指针,除初始化以外,栈顶指针始终位于栈顶元素的上一位
int stacksize;//栈的长度
}sqstack;
函数定义
void initstack(sqstack &s)
//顺序的初始化
{
s.base=new Selemtype[maxsize];//分配一块大小为maxsize的连续空间
if(!s.base)//如果分配失败就输出提示性语句
{
cout<<"未能分配空间"<<endl;
}
else{//分配成功则:
s.top=s.base;//将top和base指向同一个空间
s.stacksize=maxsize;//将栈的长度初始化
}
}
int lookstack(sqstack s){
//查看栈的长度
int length;
length=s.top-s.base;//因为数组空间是连续的,所以长度为top-base
return length;
}//返回栈顶长度
void push (sqstack &s,Selemtype e)
//入栈操作
{
if(s.top-s.base==s.stacksize)//如果数组空间的长度已经等于分配的最大长度
{
cout<<"数组空间已满"<<endl;//输出提示语句
}
else{//如果数组空间为满,则
*(s.top)=e;//元素e压入栈顶,栈顶指针加一
s.top++;
}
}
void pop(sqstack &s)
//弹栈操作
{
Selemtype e;
if(s.top==s.base)//进行判空操作
{
cout<<"顺序栈为空"<<endl;
}
else{
s.top--;//栈顶指针减一
e=*s.top;//将栈顶元素赋给e
cout<<"出栈元素为"<<e<<endl;
}
}
void gettop(sqstack s)
{
//取得栈顶元素
if(s.top==s.base)//如果栈为空,输出提示语句
{
cout<<"栈为空"<<endl;
}
else{//栈非空,用e带出栈顶元素的值
int e=*(s.top-1);
cout<<"栈顶元素为"<<e<<endl;
}
}
bool judge(sqstack S)
{//判断是否为空栈
if(S.base==S.top)
{//如果栈头栈尾指向同一个地址,说明为空栈
return false;
}
else{
return true;
}
}
void changlle(int n,int r)
{//将n进制数转换为r进制数
sqstack s;
initstack(s);//创建一个栈来保存转换结果
while(n)//利用除法取余
{
push(s,n%r);//将余数入栈
n=n/r;
}
while(judge(s))//当未到栈底一直执行弹栈操作
{
pop(s);
}
}
void clearstack(sqstack &s)
{//清空栈
s.top=s.base;
}
void destroy(sqstack &s)
{//销毁栈空间
delete[] s.base;
s.base=NULL;
s.top=NULL;
s.stacksize=0;
}
mian函数定义:
int main()
{
sqstack s;
int input,e,n,i,r;
cout<<"\t 按1开始初始化顺序栈"<<endl;
cout<<"\t 按2求顺序表长"<<endl;
cout<<"\t 按3将元素e入栈"<<endl;
cout<<"\t 按4将元素i出栈"<<endl;
cout<<"\t 按5取得栈顶元素"<<endl;
cout<<"\t 按7将十进制数n转变为r进制数"<<endl;
cout<<"\t 按8开始清空顺序栈"<<endl;
cout<<"\t 按9开始销毁顺序栈"<<endl;
cin>>input;
do{
switch(input)
{
case(1):
{
initstack(s);
break;
}
case(2):
{
cout<<"顺序栈长度为:";
int length=lookstack(s);
cout<<length<<endl;;
break;
}
case(3):
{
cout<<"入栈元素e为:"<<endl;
cin>>e;
push(s,e);
break;
}
case(4):
{
pop(s);
break;
}
case(5):
{
gettop(s);
break;
}
case(6):
{
bool tell=judge(s);
if(tell)
{
cout<<"不为空表"<<endl;
}
else{
cout<<"为空表"<<endl;
}
break;
}
case(7):
{
cout<<"请输入需转换的十进制数n"<<endl;
cin>>n;
cout<<"请输入想要转换的进制r:"<<endl;
cin>>r;
changlle(n,r);
}
case(8):
{
clearstack(s);
}
case(9):
{
destroy(s);
}
}
cout<<"\t 按1开始初始化顺序栈"<<endl;
cout<<"\t 按2开始输出栈长"<<endl;
cout<<"\t 按3将元素e入栈"<<endl;
cout<<"\t 按4将元素i出栈"<<endl;
cout<<"\t 按5取得栈顶元素"<<endl;
cout<<"\t 按6判断是否为空栈"<<endl;
cout<<"\t 按7将十进制数n转变为r进制数"<<endl;
cout<<"\t 按8开始清空顺序栈"<<endl;
cout<<"\t 按9开始销毁顺序栈"<<endl;
cin>>input;
}while(input!=-1);
}
运行截图:
链栈
头文件定义
#include<iostream>
using namespace std;
typedef int elemtype;
结构体定义
typedef struct Stacknode{//定义节点结构体
elemtype data;
struct Stacknode *next;
}Stacknode;
函数定义:
void initstack(linkstack &s)
//初始化链栈,构建一个空栈,不必设置头指针
{
s=NULL;
}
void push(linkstack &s,elemtype e)
//将元素e入栈
{
linkstack p;
p=new Stacknode;//生成新节点
p->data=e;//为节点的数据域赋值
p->next=s;//将新节点链接到链尾
s=p;//将s指向链尾
}
elemtype lengthstack(linkstack s)
//求链栈的长度
{
elemtype length=0;//初始化长度
while(s)//从链表的开头依次向后遍历,未到达表尾NULL就一直向后
{
length++;
s->next=s;//修改节点的指针域,使得指向下一个节点
}
return length;//返回链栈的长度
}
void pop(linkstack &s,elemtype &e)
//进行弹栈操作,通过e将弹出元素数值带出
{
linkstack p;//设置一个指针来方便后面的指针修改和删除
if(s==NULL)
//先判断链栈是否为空
{
cout<<"栈为空"<<endl;
}
else{
e=s->data;//得到栈顶的元素值
p=s;//用p临时保存栈顶元素空间,以备释放
s=s->next;//将原来的栈顶指针指向下一个指针
delete p;//释放原栈顶元素空间
}
}
elemtype gettop(linkstack s)
//取得栈顶元素
{
if(s!=NULL)//进行链栈的判空
{
return s->data;//不为空,则返回栈顶元素值
}
else{
return -1;//为空则返回-1
}
}
bool judge(linkstack s)
//判断栈是否为空
{
if(s==NULL)
{//如果栈为空,返回false
return false;
}
else{
//如果不空,返回true
return true;
}
}
elemtype getlength(linkstack s)
//取得链栈的长度
{
elemtype length=0;
while(s)//当链表未到达队尾时,一直向后循环+1
{
length++;
s=s->next;//指针向后移动
}
return length;
}
void deletestack(linkstack &s)
//销毁链栈
{
linkstack p;//设置一个指针来方便后面的指针修改和删除
while(s)
{
p=s->next;//用p临时保存栈顶元素空间,以备释放
s=s->next;//s向后遍历,直至到达队尾
delete(p);//释放p元素的空间
}
}
main函数定义:
int main(){
int input;
linkstack s;
elemtype e=0,n,length,top;
bool flag;
cout<<"\t 按1开始初始化链栈"<<endl;
cout<<"\t 按2开始将元素n入栈"<<endl;
cout<<"\t 按3开始元素e出栈"<<endl;
cout<<"\t 按4取得栈顶元素"<<endl;
cout<<"\t 按5判断是否为空表"<<endl;
cout<<"\t 按6输出栈长"<<endl;
cout<<"\t 按7销毁栈"<<endl;
cin>>input;
do{
switch(input)
{
case(1):
{
initstack(s);
break;
}
case(2):
{
cout<<"请输入想要输入的元素n"<<endl;
cin>>n;
push(s,n);
break;
}
case(3):
{
pop(s,e);
cout<<"出栈元素e为"<<e<<endl;
break;
}
case(4):
{
top=gettop(s);
if(top!=-1){
cout<<"栈顶元素为:"<<top<<endl;
}
else{
cout<<"栈为空,无元素"<<endl;
}
break;
}
case(5):
{
if(judge(s))
{
cout<<"不为空表"<<endl;
}
else{
cout<<"为空表"<<endl;
}
break;
}
case(6):
{
length=getlength(s);
cout<<"链栈长为"<<length<<endl;
break;
}
case(7):
{
deletestack(s);
break;
}
}
cout<<"\t 按1开始初始化链栈"<<endl;
cout<<"\t 按2开始将元素n入栈"<<endl;
cout<<"\t 按3开始元素e出栈"<<endl;
cout<<"\t 按4取得栈顶元素"<<endl;
cout<<"\t 按5判断是否为空表"<<endl;
cout<<"\t 按6输出栈长"<<endl;
cout<<"\t 按7销毁栈"<<endl;
cin>>input;
}while(input!=-1);
}
运行截图:
队列
循环队列
头文件定义
#include<iostream>
#define maxsize 100
using namespace std;
typedef int qelemtype;
结构体定义
//如果设有循环队列,必须为设定一个最大队列长度,如果用户无法预估队列的最大元素,应该用链队
typedef struct{//循环队列的定义
qelemtype *base;//储存空间的基地址
int front;//头指针
int rear;//尾指针
}sqqueue;
函数定义
bool initsqqueue(sqqueue &s)
{
s.base=new qelemtype[maxsize];//为队列分配一个最大容量为maxsize的空间
if(s.base==NULL)
{
return false;
}
else
{//头指针和尾指针置零,队列为空
s.front=0;
s.rear=0;
return true;
}
}
int getlength(sqqueue s)
{
int length;
//返回元素的个数,即队列的长度
length=(s.rear-s.front+maxsize)%maxsize;
return length;
}
bool enqueue(sqqueue &s,qelemtype e)
{
if((s.rear+1)%maxsize==s.front)//尾指针在循环意义上加一后等于头指针,
//表明队满
{
return false;
}
else{
s.base[s.rear]=e;//新元素插入队尾
s.rear=(s.rear+1)%maxsize;//队尾指针加一
return true;
}
}
bool dequeue(sqqueue &s,qelemtype &i)
{
if(s.front==s.rear)//队为空
{
return false;
}
else{
i=s.base[s.front];//保存队头元素
s.front=(s.front+1)%maxsize;//队头指针加1
return true;
}
}
int gettop(sqqueue s)
{
if(s.front!=s.rear)//队列不为空
{
return s.base[s.front];//返回队头元素的值,队头指针不变
}
else{
return -1;
}
}
void clearsqqueue(sqqueue &s)
{
s.front=0;
s.rear=0;
}
void destroy(sqqueue &s)
{
delete[] s.base;//清空数组空间
s.front=0;
s.rear=0;
}
void lookall(sqqueue s)
{
if(s.front==s.rear){
cout<<"循环队列为空"<<endl;
}
else{
while(s.front!=s.rear)
{
cout<<s.base[s.front]<<" ";
s.front=(s.front+1)%maxsize;
}
cout<<endl;
}
}
main函数定义
int main()
{
int input;
int e,i,length,top;
sqqueue s;
bool flag1,flag2,flag3;
cout<<"\t 按1开始初始化循环队列"<<endl;
cout<<"\t 按2开始求队列长度"<<endl;
cout<<"\t 按3开始将元素e入队尾"<<endl;
cout<<"\t 按4开始将队头元素i出列"<<endl;
cout<<"\t 按5开始取得队头元素"<<endl;
cout<<"\t 按6开始清空队列"<<endl;
cout<<"\t 按7开始销毁队列"<<endl;
cout<<"\t 按8开始输出循环队列全部元素"<<endl;
cout<<"\t 按-1开始退出程序"<<endl;
cin>>input;
do{
switch(input)
{
case(1):
{
flag1=initsqqueue(s);
if(flag1)
{
cout<<"循环队列初始化成功"<<endl;
}
else{
cout<<"循环队列建立失败"<<endl;
}
break;
}
case(2):
{
length=getlength(s);
cout<<"循环队列的长度为"<<length<<endl;
break;
}
case(3):
{
cout<<"请输入想要加入队尾的元素e"<<endl;
cin>>e;
flag2=enqueue(s,e);
if(flag2)
{
cout<<"元素e成功加入队尾"<<endl;
}
else{
cout<<"队列已经装满,无法加入"<<endl;
}
break;
}
case(4):
{
flag3=dequeue(s,i);
if(flag3)
{
cout<<"队头元素"<<i<<"已经出队"<<endl;
}
else
{
cout<<"队列为空,无法弹出元素"<<endl;
}
break;
}
case(5):
{
top=gettop(s);
if(top!=-1)
cout<<"队列头元素为"<<top<<endl;
else{
cout<<"队列为空"<<endl;
}
break;
}
case(6):
{
clearsqqueue(s);
break;
}
case(7):
{
destroy(s);
break;
}
case(8):
{
lookall(s);
break;
}
}
cout<<"\t 按1开始初始化循环队列"<<endl;
cout<<"\t 按2开始求队列长度"<<endl;
cout<<"\t 按3开始将元素e入队尾"<<endl;
cout<<"\t 按4开始将队头元素i出列"<<endl;
cout<<"\t 按5开始取得队头元素"<<endl;
cout<<"\t 按6开始清空队列"<<endl;
cout<<"\t 按7开始销毁队列"<<endl;
cout<<"\t 按8开始输出循环队列全部元素"<<endl;
cout<<"\t 按-1开始退出程序"<<endl;
cin>>input;
}while(input!=-1);
return 0;
}
运行截图:
链队列:
头文件定义:
#include<iostream>
using namespace std;
typedef int qelemtype;
结构体定义:
typedef struct qnode{
qelemtype data;
struct qnode *next;
}qnode;
typedef qnode* queueptr;
typedef struct{
queueptr front; //队头指针
queueptr rear; //队尾指针
}linkqueue;
函数定义:
void initqueue(linkqueue &s)
{//构建一个空队列s
s.front=s.rear=new qnode;//生成新节点作为头节点,linkqueue的队头和队尾指向此节点
s.front->next=NULL;//头节点的指针域置为空
}
int getlength(linkqueue s)
{//返回队列元素的个数
int length=0;
queueptr p;//生成一个节点类指针,方便进行链表遍历
if(s.front==s.rear)//判断是否为空表
{
return 0;
}
p=s.front->next;//p指向首元节点
while(p)
{
length++;
p=p->next;//向后移动,直至到达队尾
}
return length;
}
bool enqueue(linkqueue &s,qelemtype e)
{//将元素e插入成为新的队尾元素
queueptr p;//生成一个节点类指针,方便对节点的数据和指针进行操作
p=new qnode;
if(p==NULL)//如果空间申请失败,返回false
{
return false;
}
p->data=e;//将节点p的数据置为e
p->next=NULL;//p的指针域置为NULL
s.rear->next=p;//s的尾部置为p
s.rear=p;//将怕置为新的尾部
return true;
}
bool dequeue(linkqueue &s,qelemtype &i)
{//删除s的队头元素,用i返回其值
if(s.front==s.rear)//若队列为空,返回false
{
return false;
}
queueptr p;//生成一个节点类指针,方便对节点的数据和指针进行操作
p=s.front->next;//p指向首元节点
i=p->data;//i保存队头元素
s.front->next=p->next;//将首元节点的指针修改为原首元节点的后一位
if(s.rear==p)//针对只有一个元素的特殊情况,首元节点和尾节点为同一个
{
s.rear=s.front;//最后一个元素被删,队尾指针指向头指针
}
delete p;//释放原队头元素空间
return true;
}
qelemtype gettop(linkqueue s)
{//返回s的队头元素,不修改指针
if(s.front!=s.rear)
{//返回队头元素的值,队头指针不变
return s.front->next->data;
}
else{//为空队
return -1;
}
}
void clearall(linkqueue &s)
{//清空队列
s.front=s.rear;
}
void destroy(linkqueue &s)
{//销毁队列空间
while(s.front)//当队列未到达队尾
{
s.rear=s.front->next;//s的尾部保存s的头部的下一位的指针
delete(s.front);//释放原s的头部空间
s.front=s.rear;//将新s的头部置为保存的s的尾部指针,以便向后遍历
}
}
void print(linkqueue s)
{//打印队列的数据元素
if(s.front==s.rear)//队列为空
{
cout<<"队列为空"<<endl;
}
queueptr ptr=s.front->next;//使ptr指向首元节点
while(ptr!=s.rear)
{
cout<<ptr->data<<" ";
ptr=ptr->next;//ptr向下遍历
}
cout<<ptr->data<<endl;
}
bool judge(linkqueue s)
{//判断是否为空表
if(s.front==s.rear)
{
return true;
}
return false;
}
main函数定义:
int main()
{
int input;
linkqueue s;
qelemtype e,i,x;
int length;
bool flag1,flag2,flag3;
cout<<"\t 按1开始初始化链队"<<endl;
cout<<"\t 按2开始求链队长度"<<endl;
cout<<"\t 按3开始将元素e插入队尾"<<endl;
cout<<"\t 按4开始链队头元素i出队"<<endl;
cout<<"\t 按5取得队头元素x"<<endl;
cout<<"\t 按6开始清空链队"<<endl;
cout<<"\t 按7开始销毁链队"<<endl;
cout<<"\t 按8判断链队是否为空"<<endl;
cout<<"\t 按9开始打印队列元素"<<endl;
cout<<"\t 按-1退出操作"<<endl;
cin>>input;
do{
switch(input)
{
case(1):
{
initqueue(s);
break;
}
case(2):
{
length=getlength(s);
cout<<"链表的长度为"<<length<<endl;
break;
}
case(3):
{
cout<<"请输入想要插入的元素e"<<endl;
cin>>e;
flag1= enqueue(s,e);
if(flag1)
{
cout<<"元素e插入成功"<<endl;
}
else{
cout<<"元素插入失败"<<endl;
}
break;
}
case(4):
{
flag2=dequeue(s,i);
if(flag2)
{
cout<<"元素i:"<<i<<"已出队"<<endl;
}
else{
cout<<"队列为空,无元素可以出队"<<endl;
}
break;
}
case(5):
{
x=gettop(s);
if(x!=-1)
{
cout<<"队头元素为"<<x<<endl;
}
else{
cout<<"队列为空"<<endl;
}
break;
}
case(6):
{
clearall(s);
break;
}
case(7):
{
destroy(s);
break;
}
case(8):
{
flag3=judge(s);
if(flag3)
{
cout<<"为空队列"<<endl;
}
else{
cout<<"不为空队列"<<endl;
}
break;
}
case(9):
{
print(s);
break;
}
}
cout<<"\t 按1开始初始化链队"<<endl;
cout<<"\t 按2开始求链队长度"<<endl;
cout<<"\t 按3开始将元素e插入队尾"<<endl;
cout<<"\t 按4开始链队头元素i出队"<<endl;
cout<<"\t 按5取得队头元素x"<<endl;
cout<<"\t 按6开始清空链队"<<endl;
cout<<"\t 按7开始销毁链队"<<endl;
cout<<"\t 按8判断链队是否为空"<<endl;
cout<<"\t 按9开始打印队列元素"<<endl;
cout<<"\t 按-1退出操作"<<endl;
cin>>input;
}while(input!=-1);
}
运行截图:
递归汉诺塔
#include<iostream>
using namespace std;
int m=0;
void move(char A,int n,char C){
cout<<"总移动的次数"<<++m<<endl;
cout<<"移动过程次数"<<n<<","<<A<<","<<C<<endl;
}
void Hanio(int n,char A,char B,char C){
if(n==1)
{
move(A,1,C);
}
else{
Hanio(n-1,A,C,B);
move(A,n,C);
Hanio(n-1,B,A,C);
}
}
int main(){
int n;
cout<<"需要移动的圆盘总个数:"<<endl;
cin>>n;
char A,B,C;
cout<<"请输入三个柱子的名称"<<endl;
cin>>A;
cin>>B;
cin>>C;
Hanio(n,A,B,C);
}
字符串
头文件定义:
#include<stdio.h>
#include<iostream>
using namespace std;
结构体定义
#include<stdio.h>
#include<iostream>
using namespace std;
函数定义:
void Inputstring(SString &s,char ch1[]){//将ch1数组的内容输入进字符串s中
int i=0;
while(ch1[i]!='\0'){//当ch1未到达末尾,将ch1的内容赋给s
s.str[i+1]=ch1[i];//将ch1的内容输入s中,s的字符串内容以1作为开始
i++;
}
s.str[i+1]='\0';//将字符串封上'\0',使其符合字符串的特征
s.length=i;//s的长度为去除'\0'的长度。
}
void Outputstring(SString s){//输出字符串s的内容
if(s.length!=0){//判断s的内容是否为空,如果非空就输出
for(int i=1;i<=s.length;i++){//从第一个字符到最后一个字符,依次输出
cout<<s.str[i]<<" ";
}
cout<<endl;
}
else{
cout<<"字符串为空"<<endl;
}
}
int stringlength(SString s){//返回字符串s的长度
return s.length;
}
int StrCompare(SString s,SString t){//比较字符串的ASCiLL大小和字符串的长度,如果相等返回0,字符不相等就返回字符的差值
int i=1,j=1;
for(i=1,j=1;i<=s.str[i]&&j<=t.length;i++,j++){//循环比较S和T的ASCILL码大写,如果不相等就返回差值
if(s.str[i]!=t.str[j]){
return s.str[i]-t.str[i];
}
}
if(s.length!=t.length){
return s.length-t.length;//比较两个字符串的长度,返回长度差值
}
return 0;
}
bool StrCat(SString &s,SString t){//将字符串t黏贴在字符串s后面,操作成功返回true,操作失败返回false
int s_length,t_length,i;//将两个变量赋值为,S和T的长度,方便后面的操作
s_length=s.length;
t_length=t.length;
if(s_length+t_length>maxsize){//判断黏贴操作是否合法,如果黏贴后的字符串长度长于maxsize,操作非法
return false;
}
else{//从t的第一个字符到t的'\0'都赋给从s原尾部的'\0'到后面的空间
for(i=1;i<=t_length+1;i++){
s.str[s.length+1]=t.str[i];
s.length++;
}
s.length--;//减去字符串的'\0'位置
return true;
}
}
bool StringCopy(SString &s,SString t){//将字符串s的内容替换为字符串t的内容,成功返回true,失败返回false
int i,t_length;
t_length=t.length;
if(t_length>maxsize){//如果t的长度超过maxsize,操作不合法,返回false
return false;
}
else{//从t的第一个字符到t的'\0'都赋给s的字符串
for(i=1;i<=t_length+1;i++){
s.str[i]=t.str[i];
}
s.length=t.length;//将s的长度改为t的长度
return true;
}
}
bool SubString(SString s,SString &sub,int pos,int len){//从S的第pos位置开始截取len位组成新字符串sub,成功返回true,失败返回false
int i;
if(pos>s.length||pos<=0||len>s.length||len<=0||len>s.length-pos){//合法性检查,如果pos<=0或者pos超过了s的长度或者len的长度<=0或者len比合法长度长,返回false
return false;
}
else{//从pos位(包括pos)向后截取len位组成新的sub字符串
for(i=1;i<=len;i++,pos++){//从s的pos位开始为sub赋值
sub.str[i]=s.str[pos];
}
sub.str[len+1]='\0';//将字符串封上'\0',使其符合字符串的特征
sub.length=len;//sub的长度就是len的长度
return true;
}
}
int Index_BF(SString s,SString t,int pos){//从s的第pos位置开始找子串t,返回s中与t完全相同的位置。如果不存在返回0
int i=pos,j=1;//初始化
while(i<=s.length&&j<=t.length){//两个串均为比较到串尾
if(s.str[i]==t.str[j]){//继续比较后继字符
i++;
j++;
}
else{//指针后退重新开始匹配
i=i-j+2;
j=1;
}
}
if(j>t.length){
return i-t.length;//匹配成功
}
else{
return 0;//匹配失败
}
}
int Index_KMP(SString s,SString t,int pos,int next[]){//l利用next数组来求字符串t的回退距离
int i=pos,j=1;
while(i<s.length&&j<=t.length){
if(j==0||s.str[i]==t.str[j]){
i++;
j++;
}
else{
j=next[j];
}
}
if(j>t.length){
return i-t.length;
}
else{
return 0;
}
}
void get_next(SString t,int next[]){//求i位的最大前后缀集合长度
int i=1;
next[i]=0;//next数组的初值默认为0
int j=0;
while(i<t.length){
if(j==0||t.str[i]==t.str[j]){
i++;
j++;
next[i]=j;
}
else{
j=next[j];
}
}
}
void StrCount(SString s){//统计字符串中的A~Z个数
int *zmcount;//用于承载字符统计结果
int res,sum=0;
zmcount=new int[maxsize];
int i,j,k=0;
zmcount[maxsize]={0};//为数组赋初值,防止数据有误
for(j=65,k=0;j<=90&&k<maxsize;j++,k++){//从A字符开始和字符串中的内容比较
zmcount[k]=0;//统计结果初始化
for(i=1;i<=s.length;i++){//从字符串的开头开始比较
if((int)s.str[i]==j){
zmcount[k]+=1;//发现于字符相同的就加一
}
}
}
//展示zmcount数组内容
for(i=0;i<26;i++){
res=zmcount[i];
sum+=res;
cout<<(char)(i+65)<<"的个数为:"<<res<<endl;//强制字符串转换
}
cout<<"总大写字母统计个数"<<sum<<endl;
}
bool CheckStr(SString S){//判断S中所给的栈的操作序列是否合法(栈的初态和终态均为空,'I'和'O'分别表示入栈和出栈操作)
//正确返回true,错误返回false
int i,j=0,k=0;
//,扫描这个序列任何位置时,O的个数(出栈次序)都小于I的个数(入栈次序),
//若大于,则不合法序列,整个序列都扫描后,O的个数都应该等于I的个数,否则为不合法序列。
for(i=1;i<=S.length;i++){
if(S.str[i]=='I'){
j++;
}
else if(S.str[i]=='O'){
k++;
if(k>j){
return false;//当出栈操作多于入栈操作时,不需要判断整个字符串,可以直接返回false
}
}
}
if(j==k){
return true;
}
else{
return false;
}
}
int newstrcat(SString &s1,SString &s2){
int len1,len2,i,j;
len1=s1.length+1;
len2=s2.length+1;
if(len1+len2>=20){
for(i=len1,j=1;j+i<=20;i++,j++){
s1.str[i+1]=s2.str[j];
s1.length++;
}
s1.str[i+1]='\0';
return 1;
}
return 0;
}
main函数定义:
#include"comdef.h"
#include"structdef.h"
#include"stringapp.h"
int main(){
SString s,t,sub;
char ch1[maxsize+1];
int input,compareres,Slength;
bool strcat,strcopy;
cout<<"1.输入字符串内容"<<endl;
cout<<"2.输出字符串内容"<<endl;
cout<<"3.字符串的长度"<<endl;
cout<<"4.将字符串t连到字符串s后面"<<endl;
cout<<"5.比较字符串s和字符串t的大小"<<endl;
cout<<"6.将字符串t的内容复制到字符串s"<<endl;
cout<<"7.从字符串的的pos位开始截取len位组成新的字符串"<<endl;
cout<<"8.在字符串s的第pos位中查找子串t(BF算法)"<<endl;
cout<<"9.在字符串s的第pos为中查找子串(KMP算法)"<<endl;
cout<<"10.统计字符串中的A~Z个数"<<endl;
cout<<"11.判断栈中的序列是否合法"<<endl;
cout<<"12.20位的strcat"<<endl;
cout<<"------------------------------------------------------------------"<<endl;
cin>>input;
do{
switch(input){
case(1):{
getchar();
cout<<"请输入一个字符串:"<<endl;
gets(ch1);
Inputstring(s,ch1);
break;
}
case(2):{
cout<<"字符串为:";
Outputstring(s);
break;
}
case(3):{
Slength=stringlength(s);
cout<<"字符串的长度为:"<<Slength<<endl;
break;
}
case(4):{
cout<<"请输入字符串t的内容:";
getchar();
gets(ch1);
Inputstring(t,ch1);
strcat=StrCat(s,t);
int strlen;
if(strcat){
cout<<"已成功将字符串t黏贴到字符串s后面"<<endl;
cout<<"新字符串的内容为:";
Outputstring(s);
cout<<endl;
strlen=stringlength(s);
cout<<"新字符串的长度为:"<<strlen<<endl;
}
else{
cout<<"字符串黏贴失败"<<endl;
}
break;
}
case(5):{
cout<<"请输入字符串t的内容"<<endl;
getchar();
gets(ch1);
Inputstring(t,ch1);
compareres=StrCompare(s,t);
if(compareres==0){
cout<<"两个字符串相等"<<endl;
}
else if(compareres>0){
cout<<"字符串s大于字符串t"<<endl;
}
else if(compareres<0){
cout<<"字符串s小于字符串t"<<endl;
}
break;
}
case(6):{
int strlen;
cout<<"请输入字符串t的内容:";
getchar();
gets(ch1);
Inputstring(t,ch1);
strcopy=StringCopy(s,t);
if(strcopy){
cout<<"已成功将字符串t的内容替换为字符串s的内容"<<endl;
cout<<"新字符串的内容为:";
Outputstring(s);
cout<<endl;
strlen=stringlength(s);
cout<<"新字符串的长度为:"<<strlen<<endl;
}
else{
cout<<"字符串复制失败"<<endl;
}
break;
}
case(7):{
int pos,len,strlen;
cout<<"请输入想要从哪里开始截取:";
cin>>pos;
cout<<"请输入想要截取的位数:";
cin>>len;
bool substring;
substring=SubString(s,sub,pos,len);
if(substring){
cout<<"已成功截取为新的字符串sub"<<endl;
cout<<"新字符串的内容为:";
Outputstring(sub);
cout<<endl;
strlen=stringlength(sub);
cout<<"新字符串的长度为:"<<strlen<<endl;
}
else{
cout<<"输入的截取的pos值和len值有误"<<endl;
}
break;
}
case(8):{
getchar();
cout<<"请输入子串:";
gets(ch1);
Inputstring(t,ch1);
int pos,res;
cout<<"请输入pos位:";
cin>>pos;
res=Index_BF(s,t,pos);
if(res!=0){
cout<<"子串查找成功子串,位置在字符串s的"<<res<<"上"<<endl;
}
else{
cout<<"子串查找失败,未能找到子串"<<endl;
}
break;
}
case(9):{
int next[maxsize];
getchar();
cout<<"请输入子串:";
gets(ch1);
Inputstring(t,ch1);
int pos,res;
cout<<"请输入pos位:";
cin>>pos;
get_next(t,next);
res=Index_KMP(s,t,pos,next);
if(res!=0){
cout<<"子串查找成功子串,位置在字符串s的"<<res<<"上"<<endl;
}
else{
cout<<"子串查找失败,未能找到子串"<<endl;
}
break;
}
case(10):{
getchar();
StrCount(s);
break;
}
case(11):{
getchar();
cout<<"请输入栈的操作序列:";
gets(ch1);
Inputstring(s,ch1);
bool res=CheckStr(s);
if(res){
cout<<"栈操作合法"<<endl;
}
else{
cout<<"栈操作不合法"<<endl;
}
break;
}case(12):{
int res;
getchar();
cout<<"请输入第一个字符串:"<<endl;
gets(ch1);
Inputstring(s,ch1);
cout<<"请输入第二个字符串:"<<endl;
gets(ch1);
Inputstring(t,ch1);
res=newstrcat(s,t);
if(res==1){
cout<<"新的字符串为"<<endl;
puts(s.str);
}
break;
}
}
cout<<"------------------------------------------------------------------"<<endl;
cout<<"1.输入字符串内容"<<endl;
cout<<"2.输出字符串内容"<<endl;
cout<<"3.字符串的长度"<<endl;
cout<<"4.将字符串t连到字符串s后面"<<endl;
cout<<"5.比较字符串s和字符串t的大小"<<endl;
cout<<"6.将字符串t的内容复制到字符串s"<<endl;
cout<<"7.从字符串的的pos位开始截取len位组成新的字符串"<<endl;
cout<<"8.在字符串s的第pos位中查找子串t(BF算法)"<<endl;
cout<<"9.在字符串s的第pos为中查找子串(KMP算法)"<<endl;
cout<<"10.统计字符串中的A~Z个数"<<endl;
cout<<"11.判断栈中的序列是否合法"<<endl;
cout<<"12.20位的strcat"<<endl;
cout<<"------------------------------------------------------------------"<<endl;
cin>>input;
}while(input!=-1);
}
运行截图:
二叉树
头文件定义:
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
结构体定义:
typedef char Elemtype;
typedef struct Bitnode{
int data;
struct Bitnode* Lchild;
struct Bitnode* Rchild;
}Bitnode;
typedef Bitnode* Bitree;
函数定义:
void initBitree(Bitree &T){//初始化二叉树
T=new Bitnode;//创建树节点
if(T){//如果创建成功就将左子树和右子树置空
T->Lchild=NULL;
T->Rchild=NULL;
cout<<"初始化二叉树成功"<<endl;
}
else{//如果创建失败就输出提示语句
cout<<"初始化二叉树失败"<<endl;
}
}
void createTree(Bitree &T)//先先序输入二叉树节点
{
Elemtype ch;
cin >> ch;
if(ch == '#') //读取到 NULL 结点
T = NULL; //建立空树,结束递归
else
{
T = new Bitnode; //生成树的根结点
T->data = ch;
createTree(T->Lchild); //创建根结点的左子树
createTree(T->Rchild); //创建根结点的右子树
}
}
void preorder(Bitree T){//先序输出二叉树,中左右
if(T){
cout<<(char)T->data<<" ";//输出根节点
preorder(T->Lchild);//输出左子树
preorder(T->Rchild);//输出右子树
}
}
void inorder(Bitree T){//中序输出二叉树,左中右
if(T){
inorder(T->Lchild);//输出左子树
cout<<(char)T->data<<" ";//输出根节点
inorder(T->Rchild);//输出右子树
}
}
void nextorder(Bitree T){//后序输出二叉树,左右中
if(T){
nextorder(T->Lchild);//输出左子树
nextorder(T->Rchild);//输出右子树
cout<<(char)T->data<<" ";//输出根节点
}
}
void levelorder(Bitree T){//利用队列结构,层序输出二叉树节点,根节点入队后,出队,并将它的孩子入队,重复进行
queue<Bitree> que_level;//定义队列
if(T==NULL){//判空操作
cout<<"空树"<<endl;
}
que_level.push(T);//将根节点入队
while(!que_level.empty()&&que_level.front()){//直至空队列,结束循环,front():返回队列的第一个对象
cout<<(char)que_level.front()->data<<' ';//输出队列的第一个节点(根节点)信息
if(que_level.front()->Lchild!=NULL)//判断是否有左子树
{
que_level.push(que_level.front()->Lchild);//将左子树节点入队
}
if(que_level.front()->Rchild!=NULL)//判断是否有右子树
{
que_level.push(que_level.front()->Rchild);//右子树入队
}
que_level.pop();//队列头出队列
}
}
int DepthBitree(Bitree T){//获得二叉树的深度
int L_length,R_length;
if(T==NULL){//子树的深度为0
return 0;
}
else{
L_length=DepthBitree(T->Lchild);//向左子树挖掘深度
R_length=DepthBitree(T->Rchild);//向右子树挖掘深度
if(L_length>R_length){//返回左右子树中较大层数
return L_length+1;
}
else{
return R_length+1;
}
}
}
int LeafCout(Bitree T){//统计二叉树的叶节点
if(T==NULL){//若为空树,则叶子数为0
return 0;
}
else if(T->Rchild==NULL&&T->Rchild==NULL)//若根节点的左右子树为0,则只有一个叶子
{
return 1;
}
else{//向左右子树挖掘叶子数
return LeafCout(T->Lchild)+LeafCout(T->Rchild);
}
}
int NodeCout(Bitree T){//统计二叉树的节点数
if(T==NULL)
return 0;//若为空树,则节点数为0
else{
return NodeCout(T->Lchild)+NodeCout(T->Rchild)+1;//挖掘左右子树的节点数
}
}
int singleBitree(Bitree T){//统计单分支节点数
if(!T){//若为空树,则节点数为0
return 0;
}
else{
if(T->Lchild&&!T->Rchild){//若左子树存在并且右子树不存在,返回左子树节点数
return singleBitree(T->Lchild)+1;
}
else{
if(!T->Lchild&&T->Rchild){//若右子树存在并且左子树不存在,返回右子树节点数
return singleBitree(T->Rchild)+1;
}
else{//若双分支都存在,向下挖掘节点数
return singleBitree(T->Lchild)+singleBitree(T->Rchild);
}
}
}
}
int doubleBitree(Bitree T){//统计双分支节点数
if(T==NULL){//若为空树,则节点个数为0
return 0;
}
else if(T->Lchild!=NULL&&T->Rchild!=NULL){//当前节点的左右孩子都不为空,则双分支节点个数加一
return doubleBitree(T->Lchild)+doubleBitree(T->Rchild)+1;
}
else{//当前节点只有1歌分支,继续遍历左或右子树,不加一
return doubleBitree(T->Lchild)+doubleBitree(T->Rchild);
}
}
void revoluteBiTree(Bitree BT)//将二叉树中每一个节点的左右子树交换
{
Bitree T;//供左右子树的交换中介用
if(!(BT)->Lchild && !(BT)->Rchild)//若只有根节点无需交换
return;
else//左右子树存在,将左右子树交换
{
T=(BT)->Lchild;
(BT)->Lchild=(BT)->Rchild;
(BT)->Rchild=T;
}
if((BT)->Lchild)//对左子树进行交换
{
revoluteBiTree((BT)->Lchild);
}
if((BT)->Rchild)//对右子树交换
{
revoluteBiTree((BT)->Rchild);
}
}
void Copy(Bitree T,Bitree &NewT){ //复制二叉树
if(!T){//若原二叉树为空树,将新的二叉树根节点置为NULL结束copy
NewT=NULL;
return ;
}
else{//原二叉树不为空
NewT=new Bitnode;//为新的二叉树申请节点空间
NewT->data=T->data;//复制根节点
Copy(T->Lchild,NewT->Lchild);//复制左子树
Copy(T->Rchild,NewT->Rchild);//复制右子树
}
}
bool isequals(Bitree T,Bitree NewT){
if(T==NULL&&NewT==NULL){//两颗二叉树均为空,返回true
return true;
}
if((T==NULL&&NewT!=NULL)||(T!=NULL&&NewT==NULL)){//其中只有一棵树为空
return false;
}
if(T->data!=NewT->data){//根节点值不相同
return false;
}
return isequals(T->Lchild,NewT->Lchild)&&isequals(T->Rchild,NewT->Rchild);
//两棵树不为空,且根节点值相同,分别比较该节点的左子树,右子树
}
main函数定义:
#include"comdef.h"
#include"bitreeapp.h"
int main(){
Bitree T,newT,compareT;
int input,depth,leaf,nodecout;
cout<<"--------------------------------------------------------------"<<endl;
cout<<"1.初始化二叉树"<<endl;
cout<<"2.先序输入二叉树节点"<<endl;
cout<<"3.先序遍历输出二叉树"<<endl;
cout<<"4.中序遍历输出二叉树"<<endl;
cout<<"5.后序遍历输出二叉树"<<endl;
cout<<"6.层序遍历输出二叉树"<<endl;
cout<<"7.计算二叉树的深度"<<endl;
cout<<"8.统计二叉树的叶节点"<<endl;
cout<<"9.统计二叉树的节点"<<endl;
cout<<"10.统计二叉树的单分支节点个数"<<endl;
cout<<"11.统计二叉树的双分支节点个数"<<endl;
cout<<"12.将二叉树中每一个节点的左右子树交换"<<endl;
cout<<"13.复制二叉树"<<endl;
cout<<"14.判断两个二叉树是否相等"<<endl;
cout<<"15.对一段文本进行Huffman编码和译码"<<endl;
cout<<"-1.退出程序"<<endl;
cout<<"--------------------------------------------------------------"<<endl;
cin>>input;
do{
switch(input){
case(1):{
initBitree(T);
break;
}
case(2):{
cout<<"请输入数据"<<endl;
createTree(T);
break;
}
case(3):{
cout<<"二叉树的内容为:"<<endl;
preorder(T);
cout<<endl;
break;
}
case(4):{
cout<<"二叉树的内容为:";
inorder(T);
cout<<endl;
break;
}
case(5):{
cout<<"二叉树的内容为:";
nextorder(T);
cout<<endl;
break;
}
case(6):{
cout<<"二叉树的内容为:";
levelorder(T);
cout<<endl;
break;
}
case(7):{
depth=DepthBitree(T);
cout<<"二叉树的深度为:";
cout<<depth<<endl;
break;
}
case(8):{
leaf=LeafCout(T);
cout<<"叶子数为:";
cout<<leaf<<endl;
break;
}
case(9):{
nodecout=NodeCout(T);
cout<<"节点个数为";
cout<<nodecout<<endl;
break;
}
case(10):{
int singlenode;
singlenode=singleBitree(T);
cout<<"单分支的节点数为:";
cout<<singlenode<<endl;
break;
}
case(11):{
int doublenode;
doublenode=doubleBitree(T);
cout<<"双分支的节点数为";
cout<<doublenode<<endl;
break;
}
case(12):{
revoluteBiTree(T);
cout<<"左右子树交换成功"<<endl;
break;
}
case(13):{
Copy(T,newT);
cout<<"复制结束"<<endl;
cout<<"新的二叉树内容为:";
preorder(newT);
cout<<endl;
break;
}
case(14):{
initBitree(compareT);
cout<<"请输入要比较的树的数据:";
createTree(compareT);
bool flag=isequals(T,compareT);
if(flag){
cout<<"两个二叉树相同"<<endl;
}
else{
cout<<"两个二叉树不相同"<<endl;
}
break;
}
}
cout<<"--------------------------------------------------------------"<<endl;
cout<<"1.初始化二叉树"<<endl;
cout<<"2.先序输入二叉树节点"<<endl;
cout<<"3.先序遍历输出二叉树"<<endl;
cout<<"4.中序遍历输出二叉树"<<endl;
cout<<"5.后序遍历输出二叉树"<<endl;
cout<<"6.层序遍历输出二叉树"<<endl;
cout<<"7.计算二叉树的深度"<<endl;
cout<<"8.统计二叉树的叶节点"<<endl;
cout<<"9.统计二叉树的节点"<<endl;
cout<<"10.统计二叉树的单分支节点个数"<<endl;
cout<<"11.统计二叉树的双分支节点个数"<<endl;
cout<<"12.将二叉树中每一个节点的左右子树交换"<<endl;
cout<<"13.复制二叉树"<<endl;
cout<<"14.判断两个二叉树是否相等"<<endl;
cout<<"-1.退出程序"<<endl;
cout<<"--------------------------------------------------------------"<<endl;
cin>>input;
}while(input!=-1);
}
运行截图:
图(邻接矩阵)
头文件定义:
#include<iostream>
#include<queue>
using namespace std;
#define MAXInt 32767
#define MVNum 100
结构体文件:
typedef int VerTexType; //顶点的数据类型是字符型
typedef int Arctype; //边的权值类型为整型
typedef struct {
VerTexType vexs[MVNum]; //顶点表
Arctype arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //图的顶点数和边数
int kind; //图的种类
}AMGraph;
bool visited[MVNum]; //访问标志数组
函数文件定义:
void CreateWXW(AMGraph &G){ //创建无向网
cout<<"请输入图的总顶点数和总边数"<<endl; //输入图的顶点数和边数
cin>>G.vexnum>>G.arcnum;
cout<<"请输入各个顶点的值"<<endl;
for(int i=0;i<G.vexnum;i++){ //输入顶点信息
cin>>G.vexs[i];
}
for(int i=0;i<G.vexnum;i++){ //初始化矩阵
for(int j=0;j<G.vexnum;j++){
G.arcs[i][j]=MAXInt;
}
}
int v1,v2;
int k,w,i,j;
for(k=0;k<G.arcnum;k++){
cout<<"请输入边的两个顶点和权值"<<endl;
cin>>v1>>v2>>w;
i=v1; //找到顶点的行
j=v2; //找到顶点的列
G.arcs[i][j]=w;
G.arcs[j][i]=G.arcs[i][j];
}
}
void CreateYXW(AMGraph &G){ //创建有向网
cout<<"请输入图的总顶点数和总边数"<<endl;
cin>>G.vexnum>>G.arcnum;
cout<<"请输入各个顶点的值"<<endl;
for(int i=0;i<G.vexnum;i++){
cin>>G.vexs[i];
}
for(int i=0;i<G.vexnum;i++){
for(int j=0;j<G.vexnum;j++){
G.arcs[i][j]=MAXInt;
}
}
int k,w,i,j;
int v1,v2;
for(k=0;k<G.arcnum;k++){
cout<<"请输入边的两个顶点和权值"<<endl;
cin>>v1>>v2>>w;
i=v1;
j=v2;
G.arcs[i][j]=w;
}
}
void CreateWXT(AMGraph &G){ //创建无向图
cout<<"请输入图的总顶点数和总边数"<<endl;
cin>>G.vexnum>>G.arcnum;
cout<<"请输入各个顶点的值"<<endl;
for(int i=0;i<G.vexnum;i++){
cin>>G.vexs[i];
}
for(int i=0;i<G.arcnum;i++){
for(int j=0;j<G.vexnum;j++){
G.arcs[i][j]=0;
}
}
int i,j,k;
int v1,v2;
for(k=0;k<G.arcnum;k++){
cout<<"请输入边的两个顶点"<<endl;
cin>>v1>>v2;
i=v1;
j=v2;
G.arcs[i][j]=1;
G.arcs[j][i]=G.arcs[i][j];
}
}
void CreateYXT(AMGraph &G){ //创建有向图
cout<<"请输入图的总顶点数和总边数"<<endl;
cin>>G.vexnum>>G.arcnum;
cout<<"请输入各个顶点的值"<<endl;
for(int i=0;i<G.vexnum;i++){
cin>>G.vexs[i];
}
for(int i=0;i<G.vexnum;i++){
for(int j=0;j<G.vexnum;j++){
G.arcs[i][j]=0;
}
}
int i,j,k;
int v1,v2;
for(k=0;k<G.arcnum;k++){
cout<<"请输入边的两个顶点"<<endl;
cin>>v1>>v2;
i=v1;
j=v2;
G.arcs[i][j]=1;
}
}
void inDegree_for_web(AMGraph G){ //求顶点的入度,求每一列的非空数量
int indegree[G.vexnum];
int i,j;
for(i=0;i<G.vexnum;i++){
indegree[i]=0; //初始化顶点入度数组
}
for(i=0;i<G.vexnum;i++){ //从第一列开始比较,每一行是否有非MAXInt的数存在,存在就说明有入度
for(j=0;j<G.vexnum;j++){
if(G.arcs[j][i]!=MAXInt){
indegree[i]++;
}
}
}
for(i=0;i<G.vexnum;i++){ //输出打印入度
cout<<G.vexs[i]<<"的入度为:"<<indegree[i]<<endl;
}
}
void inDegree_for_graph(AMGraph G){ //求顶点的入度,求每一列的非空数量
int indegree[G.vexnum];
int i,j;
for(i=0;i<G.vexnum;i++){
indegree[i]=0; //初始化顶点入度数组
}
for(i=0;i<G.vexnum;i++){ //从第一列开始比较,每一行是否有非MAXInt的数存在,存在就说明有入度
for(j=0;j<G.vexnum;j++){
if(G.arcs[j][i]!=0){
indegree[i]++;
}
}
}
for(i=0;i<G.vexnum;i++){ //输出打印入度
cout<<G.vexs[i]<<"的入度为:"<<indegree[i]<<endl;
}
}
void outDegree_for_web(AMGraph G){ //求图的出度,求每一行的非空数量
int outdegree[G.vexnum];
int i,j;
for(i=0;i<G.vexnum;i++){
outdegree[i]=0; //初始化顶点入度数组
}
for(i=0;i<G.vexnum;i++){ //从第一列开始比较,每一行是否有非MAXInt的数存在,存在就说明有入度
for(j=0;j<G.vexnum;j++){
if(G.arcs[i][j]!=MAXInt){
outdegree[i]++;
}
}
}
for(i=0;i<G.vexnum;i++){ //输出打印出度
cout<<G.vexs[i]<<"的出度为:"<<outdegree[i]<<endl;
}
}
void outDegree_for_graph(AMGraph G){ //求图的出度,求每一行的非空数量
int outdegree[G.vexnum];
int i,j;
for(i=0;i<G.vexnum;i++){
outdegree[i]=0; //初始化顶点入度数组
}
for(i=0;i<G.vexnum;i++){ //从第一列开始比较,每一行是否有非MAXInt的数存在,存在就说明有入度
for(j=0;j<G.vexnum;j++){
if(G.arcs[i][j]!=0){
outdegree[i]++;
}
}
}
for(i=0;i<G.vexnum;i++){ //输出打印出度
cout<<G.vexs[i]<<"的出度为:"<<outdegree[i]<<endl;
}
}
void DFS_AM_graph(AMGraph G,int v){ //深度遍历
int i;
visited[v]=true;
cout<<v<<" ";
for(i=0;i<G.vexnum;i++){
if(G.arcs[v][i]!=0 && (!visited[i])){
DFS_AM_graph(G,i);
}
}
}
void DFS_AM_web(AMGraph G,int v){ //深度遍历
int i;
visited[v]=true;
cout<<v<<" ";
for(i=0;i<G.vexnum;i++){
if(G.arcs[v][i]!=MAXInt && (!visited[i])){
DFS_AM_web(G,i);
}
}
}
void Clearvisited(AMGraph G ,bool visited[]){
for(int i=0;i<G.vexnum;i++){
visited[i]=false;
}
}
int Fisrtadjex(AMGraph G,int v){ //返回v的第一个邻接点,不存在换回-1
int i;
for(i=0;i<G.vexnum;i++){ //从行的开头对比是否有邻接边
if((G.arcs[v][i]!=0||G.arcs[v][i]!=MAXInt) && visited[i]==false){
return i;
}
}
return -1;
}
int Nextadjex(AMGraph G,int u,int w){ //返回v相对于w的下一个邻接点,u是开始节点
int i;
for(i=w;i<G.vexnum;i++){
if((G.arcs[u][i]!=0 && G.arcs[u][i]!=MAXInt) &&visited[i]==false){
return i;
}
}
return -1;
}
void BFS_AM_graph(AMGraph G,int v){ //从v节点开始广度遍历
cout<<v<<" ";
visited[v]=true;
queue<int> que_level;
que_level.push(v);
while(!que_level.empty()){
int u;
u=que_level.front();
que_level.pop();
for(int w=Fisrtadjex(G,u);w>=0;w=Nextadjex(G,u,w)){
if(!visited[w])
{
cout<<w<<" ";
visited[w]=true;
que_level.push(w);
}
}
}
}
main函数定义:
#include"comdef.h"
#include"app.h"
int main(){
AMGraph G;
int input;
cout<<"——————————————————————————————"<<endl;
cout<<"1.创建图邻接矩阵"<<endl;
cout<<"2.打印图各个顶点的入度"<<endl;
cout<<"3.打印图各个顶点的出度"<<endl;
cout<<"4.深度遍历图"<<endl;
cout<<"5.广度遍历图"<<endl;
cout<<"-1,退出程序"<<endl;
cout<<"——————————————————————————————"<<endl;
cout<<"你的选择是:";
cin>>input;
do{
switch(input){
case(1):
{
cout<<"请选择创建图的种类 1:无向网 2:有向网 3:无向图 4:有向图"<<endl;
cin>>G.kind;
switch(G.kind)
{
case(1):
{
CreateWXW(G);
break;
}
case(2):
{
CreateYXW(G);
break;
}
case(3):
{
CreateWXT(G);
break;
}
case(4):
{
CreateYXT(G);
break;
}
}
break;
}
case(2):
{
switch(G.kind)
{
case(1):
{
inDegree_for_web(G);
break;
}
case(2):
{
inDegree_for_web(G);
break;
}
case(3):
{
inDegree_for_graph(G);
break;
}
case(4):
{
inDegree_for_graph(G);
break;
}
}
break;
}
case(3):
{
switch(G.kind)
{
case(1):
{
outDegree_for_web(G);
break;
}
case(2):
{
outDegree_for_web(G);
break;
}
case(3):
{
outDegree_for_graph(G);
break;
}
case(4):
{
outDegree_for_graph(G);
break;
}
}
break;
}
case(4):
{
switch(G.kind)
{
case(1):
{
int i;
cout<<"请输入开始遍历节点:"<<" ";
cin>>i;
DFS_AM_web(G,i);
Clearvisited(G,visited);
cout<<endl;
break;
}
case(2):
{
int i;
cout<<"请输入开始遍历节点:"<<" ";
cin>>i;
DFS_AM_web(G,i);
Clearvisited(G,visited);
cout<<endl;
break;
}
case(3):
{
int i;
cout<<"请输入开始遍历节点:"<<" ";
cin>>i;
DFS_AM_graph(G,i);
Clearvisited(G,visited);
cout<<endl;
break;
}
case(4):
{
int i;
cout<<"请输入开始遍历节点:"<<" ";
cin>>i;
DFS_AM_graph(G,i);
Clearvisited(G,visited);
cout<<endl;
break;
}
}
break;
}
case(5):
{
int i;
cout<<"请输入开始遍历的节点"<<" ";
cin>>i;
BFS_AM_graph(G,i);
cout<<endl;
break;
}
}
cout<<"——————————————————————————————"<<endl;
cout<<"1.创建图邻接矩阵"<<endl;
cout<<"2.打印图各个顶点的入度"<<endl;
cout<<"3.打印图各个顶点的出度"<<endl;
cout<<"4.深度遍历图"<<endl;
cout<<"5.广度遍历图"<<endl;
cout<<"-1,退出程序"<<endl;
cout<<"——————————————————————————————"<<endl;
cout<<"你的选择是:";
cin>>input;
}while(input!=-1);
}
运行截图:
图(邻接表)
头文件定义:
#include<iostream>
#include<queue>
#include<stack>
#include<stdlib.h>
using namespace std;
#define MAXVEX 100 //最大顶点数
结构体定义:
typedef struct ArcNode{//邻接表节点
int adjvex; //邻接点的位置
struct ArcNode* nextarc; //指向下一个表的节点的指针
int weight; //边的权重
}ArcNode;
typedef struct Vnode{
char data; //顶点信息
ArcNode* firstarc; //指向第一个表节点的指针
}Vnode,AdjList[MAXVEX]; //AdjList表示邻接表类型
typedef struct ALGraph{
AdjList vertices; //头节点数组
int vexnum,arcnum; //图的当前顶点数和边数
}ALGraph;
函数定义:
void CreatMGraph(ALGraph &G) //创建无向图
{
int i,j,k;
ArcNode *s;
cout<<"请输入总顶点数,总边数"<<endl;
cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数
cout<<"请输入各个顶点值"<<endl;
for(i=0;i<G.vexnum;i++){ //输入各点,构造表头节点表
cin>>G.vertices[i].data; //输入顶点值
}
for(i=0;i<G.vexnum;i++){
G.vertices[i].firstarc = NULL; //初始化表头节点的指针域为NULL
}
for(k=0;k<G.arcnum;k++) {
cout<<"请输入一条边的两个节点"<<endl; //输入各边,构造邻接表
cin>>i>>j; //输入一条边的两个节点
s=new ArcNode; // 生成一个新节点
s->adjvex=j;
s->nextarc=G.vertices[i].firstarc; //头插法建立新节点
G.vertices[i].firstarc = s;
s=new ArcNode; //生成另一个对称的新的边节点
s->adjvex=i;
s->nextarc=G.vertices[j].firstarc;
G.vertices[j].firstarc = s;
}
}
void CreatYGraph(ALGraph &G){ //创建有向图
int i,j,k;
ArcNode *s;
cout<<"请输入总顶点数,总边数"<<endl;
cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数
cout<<"请输入各个顶点值"<<endl;
for(i=0;i<G.vexnum;i++){
cin>>G.vertices[i].data; //输入各点,构造表头节点表
}
for(i=0;i<G.vexnum;i++){
G.vertices[i].firstarc=NULL; //初始化表头节点的指针域为NULL
}
for(k=0;k<G.arcnum;k++){
cout<<"请输入一条边的两个节点"<<endl;//输入各边,构造邻接表
cin>>i>>j;
s=new ArcNode;//生成一个新节点
s->adjvex=j;
s->nextarc=G.vertices[i].firstarc;//头插法建立新节点
G.vertices[i].firstarc=s;
}
}
void CreatWWGraph(ALGraph &G){ //创建无向网
int i,j,k,w;
ArcNode *s;
cout<<"请输入总结点数和总边数"<<endl;
cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数
cout<<"请输入各个顶点的值"<<endl;
for(i=0;i<G.vexnum;i++){
cin>>G.vertices[i].data; //输入各点,构造表头节点表
}
for(i=0;i<G.vexnum;i++){
G.vertices[i].firstarc=NULL; //初始化表头节点的指针域为NULL
}
for(k=0;k<G.arcnum;k++){
cout<<"请输入一条边的两个节点和边上的权重"<<endl;
cin>>i>>j>>w; //输入各边节点和权重,构造邻接表
s=new ArcNode; //生成一个新节点
s->adjvex=j; //把该节点的邻接点的数据置为j
s->weight=w; //该节点的所在边的权重
s->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=s; //头插法
s= new ArcNode; //创建对称节点
s->adjvex=i;
s->weight=w;
s->nextarc=G.vertices[j].firstarc;
G.vertices[j].firstarc=s;
}
}
void CreatYWGraph(ALGraph &G){ //创建有向网
int i,j,w,k;
ArcNode *s;
cout<<"请输入总节点和总边数"<<endl;
cin>>G.vexnum>>G.arcnum; //输入总顶点数,总边数
cout<<"请输入各个顶点的值"<<endl;
for(i=0;i<G.vexnum;i++){
cin>>G.vertices[i].data; //输入各点,构造表头节点表
}
for(i=0;i<G.vexnum;i++){
G.vertices[i].firstarc=NULL; //初始化表头节点的指针域为NULL
}
for(k=0;k<G.arcnum;k++){
cout<<"请输入一条边上的两个节点和权重"<<endl;
cin>>i>>j>>w; //输入各边节点和权重,构造邻接表
s= new ArcNode; //生成一个新节点
s->adjvex=j; //把该节点的邻接点的数据置为j
s->weight=w; //该节点的所在边的权重
s->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=s; //头插法
}
}
void printfGraph(ALGraph G){ //图专用的邻接图打印
int i;
ArcNode *p;
for(i=0;i<G.vexnum;i++){
cout<<G.vertices[i].data<<":";
for(p=G.vertices[i].firstarc;p;p=p->nextarc){
cout<<p->adjvex<<" ";
}
cout<<endl;
}
}
void printWGraph(ALGraph G) //网专用的邻接图打印
{
int i;
ArcNode *p;
for(i=0;i<G.vexnum;i++){
printf("%c:",G.vertices[i].data);
for(p=G.vertices[i].firstarc;p;p=p->nextarc){
printf(" %d",p->adjvex);
printf("边上的权重是:%d",p->weight);
}
printf("\n");
}
}
int A[MAXVEX]; //入度数组
void count_in(ALGraph G,int A[]){ //求有向图和有向网的入度
int i,j;
for(i=0;i<G.vexnum;i++){
A[i]=0; //初始化入度数组
}
ArcNode *e;
for(j=0;j<G.vexnum;j++){ //从邻接表数组的开始统计
while(G.vertices[j].firstarc!=NULL){ //这个节点有邻接节点
A[G.vertices[j].firstarc->adjvex]++; //对应的邻接节点入度加一
e=G.vertices[j].firstarc->nextarc; //向下一个节点前进,e为当前邻接节点的下一个节点
G.vertices[j].firstarc=e;
}
}
}
void count_out(ALGraph G){ //求有向图和有向网的出度
int i,j;
int A[G.vexnum];
for(i=0;i<G.vexnum;i++){
A[i]=0;
}
ArcNode *e;
for(j=0;j<G.vexnum;j++){
while(G.vertices[j].firstarc!=NULL){
A[j]++;
e=G.vertices[j].firstarc->nextarc;
G.vertices[j].firstarc=e;
}
}
for(i=0;i<G.vexnum;i++){
cout<<G.vertices[i].data<<"的出度为:"<<A[i]<<endl;
}
}
bool visited[MAXVEX];
void clearvisited(bool visited[]){ //清空标志数组,方便多次得到深度遍历节点
for(int i=0;i<MAXVEX;i++){
visited[i]=false;
}
}
void DFS(ALGraph G,int v){ //G为邻接表,从顶点v出发,深度优先搜索遍历.类似于树的先序遍历
cout<<v<<" "; //输出第v个节点
int w;
visited[v]=true;//置其标志数组对应值为true
ArcNode *p;
p=G.vertices[v].firstarc; //p指向v的边链表的第一个边节点
while(p!=NULL){ //边节点非空
w=p->adjvex; //w是v的邻接点
if(!visited[w]){ //如果w未访问,则递归调用
DFS(G,w);
}
p=p->nextarc; //p指向下一个边节点
}
}
int FisAdjVex(ALGraph G,int V){ //找到v的第一个邻接点
int i,k;
for(i=0;i<G.vexnum;i++){
if(i==V){
k=G.vertices[i].firstarc->adjvex;
return k;
}
}
return -1; //未找到邻接点
}
int nextAdjVex(ALGraph G,int v,int w){ //找到v相对于w的下一个邻接点
int k;
ArcNode *p;
if(w<0){
return -1; //没有邻接点了
}
else{
for(p=G.vertices[v].firstarc;p;p=p->nextarc){
if(p->adjvex==w){
if(p->nextarc!=NULL){
k=p->nextarc->adjvex;
return k;
}
}
}
}
return -1;
}
int locateVertex(ALGraph G,char v){ //找到对应顶点的下标
for(int i=0;i<G.vexnum;i++){ //比对表头数据,找到就返回所在位置,没找到就返回-1
if(G.vertices[i].data==v){
return i;
}
}
return -1;
}
void BFS_AL(ALGraph G,char v0){ //邻接表的广度遍历,类似于树的层序遍历
int i,j,v;
ArcNode *p;
cout<<v0<<" "; //打印顶点v0
i=locateVertex(G,v0); //找到v0对应的下标
visited[i]=true; //顶点已被访问
queue<char> que_level; //创建队列
que_level.push(v0); //将顶点v0入队
while(!que_level.empty()){
v=que_level.front(); //将顶点元素v出队,开始访问v的所有邻接点
i=locateVertex(G,v); //得到顶点u的对应下标
que_level.pop();
for(p=G.vertices[i].firstarc;p;p=p->nextarc){ //遍历顶点v的邻接点
j=p->adjvex; //j是v的邻接点
if(!visited[j]){ //如果顶点p未被访问
cout<<G.vertices[j].data<<" "; //打印顶点p
visited[j]=true; //顶点p已被访问
que_level.push(G.vertices[j].data); //将顶点p入队
}
}
}
}
void Toposort(ALGraph G){
count_in(G,A); //初始化建立各个顶点的入度表
stack<int> S; //建立空栈
int Nodecount=0; //拓扑排序检测
int v;
cout<<"拓扑序列:"<<endl;
for(int i=0;i<G.vexnum;i++){
if(A[int(G.vertices[i].data-'0')]==0){ //假如节点的入度为0,就进栈
S.push(i);
}
}
while(!S.empty()){ //当栈为非空
v=S.top(); //得到栈的栈顶
S.pop(); //弹栈
cout<<v<<" ";//输出拓扑排序序列
Nodecount++;
ArcNode *temp;
temp=G.vertices[v].firstarc;//指向v的第一个邻接点
while(temp!=NULL){
A[int(G.vertices[temp->adjvex].data-'0')]--;//v的每个邻接点入度减一
if(A[int(G.vertices[temp->adjvex].data-'0')]==0){ //若入度减为0,入栈
S.push(temp->adjvex);
}
temp=temp->nextarc;//指向下一个邻接点
}
}
if(Nodecount<G.vexnum){ //判断是否有回路
cout<<"图有回路"<<endl;
}
}
main函数定义:
#include"comdef.h"
#include"app.h"
int main(){
ALGraph G;
int input,kind,v;
char v0;
cout<<"——————————————————————————————"<<endl;
cout<<"\t1.创建无向图/有向图/无向网/有向网(邻接表)"<<endl;
cout<<"\t2.打印邻接表"<<endl;
cout<<"\t3.深度遍历"<<endl;
cout<<"\t4.计算有向图/网的入度"<<endl;
cout<<"\t5.计算有向图/网的出度"<<endl;
cout<<"\t6.广度遍历"<<endl;
cout<<"\t7.求AOV网的拓扑序列"<<endl;
cout<<"\t-1,退出程序"<<endl;
cout<<"——————————————————————————————"<<endl;
cout<<"你的选择是:";
cin>>input;
do{
switch(input){
case(1):
{
cout<<"1.无向图"<<endl;
cout<<"2.有向图"<<endl;
cout<<"3.无向网"<<endl;
cout<<"4.有向网"<<endl;
cout<<"请选择创建图的类型:";
cin>>kind;
switch(kind){
case(1):
{
CreatMGraph(G);
break;
}
case(2):
{
CreatYGraph(G);
break;
}
case(3):
{
CreatWWGraph(G);
break;
}
case(4):
{
CreatYWGraph(G);
break;
}
}
break;
}
case(2):
{
switch(kind){
case(1):{
printfGraph(G);
break;
}
case(2):{
printfGraph(G);
break;
}
case(3):{
printWGraph(G);
break;
}
case(4):{
printWGraph(G);
break;
}
}
break;
}
case(3):
{
cout<<"请输入开始深度遍历节点:"<<" ";
cin>>v;
DFS(G,v);
clearvisited(visited);
cout<<endl;
break;
}
case(4):
{
count_in(G,A);
for(int i=0;i<G.vexnum;i++){
cout<<G.vertices[i].data<<"的入度为:"<<A[i]<<endl;
}
break;
}
case(5):
{
count_out(G);
break;
}
case(6):
{
cout<<"请输入开始广度遍历节点:"<<" ";
cin>>v0;
BFS_AL(G,v0);
clearvisited(visited);
cout<<endl;
break;
}
case(7):
{
Toposort(G);
cout<<endl;
break;
}
}
cout<<"——————————————————————————————"<<endl;
cout<<"\t1.创建无向图/有向图/无向网/有向网(邻接表)"<<endl;
cout<<"\t2.打印邻接表"<<endl;
cout<<"\t3.深度遍历"<<endl;
cout<<"\t4.计算有向图/网的入度"<<endl;
cout<<"\t5.计算有向图/网的出度"<<endl;
cout<<"\t6.广度遍历"<<endl;
cout<<"\t7.求AOV网的拓扑序列"<<endl;
cout<<"\t-1,退出程序"<<endl;
cout<<"——————————————————————————————"<<endl;
cout<<"你的选择是:";
cin>>input;
}while(input!=-1);
}
运行截图:
查找
头文件定义:
#include<iostream>
#include<random>
using namespace std;
typedef int keytype;
#define MAXLEN 100
结构体定义:
typedef struct{
keytype key;
}Elemtype;
typedef struct{
Elemtype R[MAXLEN+1];
int length;
}SSTable;
typedef SSTable* seq;
函数定义:
void Createseq(seq &ST,int num){ //创建顺序表,向表中输入num个数据
for(int i=1;i<=num;i++){
cout<<"请输入数据"<<" ";
cin>>ST->R[i].key;
}
ST->length=num;
}
int search_bin(seq ST,keytype key){ //折半查找,
int low=1,mid;
int high=ST->length;
while(low<=high){
mid=(low+high)/2;
if(key==ST->R[mid].key){ //找到待查元素
return mid;
}
else if(key<ST->R[mid].key){ //就绪在前一子表进行查找
high=mid-1;
}
else{
low=mid+1; //在后一子表查找
}
}
return 0; //表中不存在待查元素
}
void search_seq(seq ST,keytype num){
int i;
for(i=ST->length;i>=1;i--){
if(ST->R[i].key==num)
{
cout<<"该元素的位置为:"<<i<<endl;
break;
}
}
if(i==0){
cout<<"该元素不在该表中"<<endl;
}
}
main函数定义:
#include"comdef.h"
#include"app.h"
int main(){
int input;
seq ST;
cout<<"1.输入顺序表序列"<<endl;
cout<<"2.顺序查找"<<endl;
cout<<"3.折半查找"<<endl;
cout<<"——————————————————————————"<<endl;
cin>>input;
do
{
switch(input)
{
case(1):
{
int num;
cout<<"请输入顺序表的个数:"<<" ";
cin>>num;
Createseq(ST,num);
cout<<"输入结束"<<endl;
break;
}
case(2):
{
int key;
cout<<"请输入欲查找数据"<<endl;
cin>>key;
search_seq(ST,key);
break;
}
case(3):
{
keytype key;
cout<<"请输入欲查找数据"<<endl;
cin>>key;
int res=search_bin(ST,key);
if(res!=0)
{
cout<<"该元素的位置为:"<<res<<endl;
}
else{
cout<<"该元素不在顺序表中"<<endl;
}
break;
}
}
cout<<"1.输入顺序表序列"<<endl;
cout<<"2.顺序查找"<<endl;
cout<<"3.折半查找"<<endl;
cout<<"——————————————————————————"<<endl;
cin>>input;
}while(input!=-1);
}
运行截图:
排序和二叉排序树
排序
头文件定义:
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
#define MAXSIZE 100
结构体定义:
typedef int ElemType;
typedef struct {
ElemType *data;
int length;
}sqlist;
函数定义:
void init(sqlist &L){ //初始化顺序表
L.data= new ElemType [MAXSIZE+1];
if(L.data==NULL)
{
cout<<"未申请到空间"<<endl;
}
L.length=MAXSIZE;
}
void Create_raw_data(sqlist &L){ //产生一个无序待排数据
for(int i=1;i<L.length;i++)
{
L.data[i]=rand()%100;
}
}
void destroydata(sqlist &L){
delete L.data;
cout<<"销毁成功"<<endl;
}
void show(sqlist L){
for(int i=1;i<L.length;i++)
{
cout<<L.data[i]<<" ";
}
}
void InsertSort(sqlist &L){ //对顺序表进行直接排序
int i,j;
for(i=2;i<=L.length;i++){
if(L.data[i]<L.data[i-1])
{
L.data[0]=L.data[i]; //将待插入的记录暂存到监视哨
for(j=i-1;L.data[0]<L.data[j];j--){ //在前i-1大小的已排好序的子表中查找需要插入的位置
L.data[j+1]=L.data[j]; //记录逐个后移,直至找到插入位置
}
L.data[j+1]=L.data[0]; //将r[0]即原r[i],插入正确位置
}
}
cout<<"插入排序成功!"<<endl;
}
void Bubblesort(sqlist &L){
int m=L.length-1,flag=1; //flage用来标记某一趟排序是否发生交换
while((m>0)&&(flag==1))
{
flag=0; //flag置为0,如果本趟排序没有发生交换,则不会执行下一趟排序
for(int j=1;j<=m;j++){
if(L.data[j]>L.data[j+1])
{
flag=1; //flag置为1,表示本趟发生了交换
int t=L.data[j];
L.data[j]=L.data[j+1];
L.data[j+1]=t; //交换前后两个记录
}
}
m--;
}
cout<<"冒泡排序成功"<<endl;
}
int Partition(sqlist &L,int low,int high){ //对顺序表L中的子表r[low..high]进行排序,韩慧枢轴位置
L.data[0]=L.data[low]; //用子表的第一个记录做枢轴记录
int privotkey=L.data[low]; //枢轴记录关键字保存在privotkey中
while(low<high)
{
while(low<high&&L.data[high]>=privotkey)
{
high--;
}
L.data[low]=L.data[high]; //将比枢轴记录小的记录移到低端
while(low<high&&L.data[low]<=privotkey)
{
low++;
}
L.data[high]=L.data[low]; //将比枢轴记录大的记录移到高端
}
L.data[low]=L.data[0]; //枢轴记录到位
return low; //返回枢轴位置
}
void Qsort(sqlist &L,int low,int high){ //d对顺序表中的子序列L.data[low..high]做快速排序
if(low<high){ //长度大于1
int pivotloc=Partition(L,low,high); //将L.data[low..high]一分为二,pivotloc是枢轴位置
Qsort(L,low,pivotloc-1); //对左子表递归排序
Qsort(L,pivotloc+1,high);//对右子表递归排序
}
}
void Quicksort(sqlist &L){ //快速排序
Qsort(L,1,L.length);
}
main函数定义:
#include"comdef.h"
#include"app.h"
int main(){
sqlist L;
int input;
cout<<"——————————————————————"<<endl;
cout<<"1.生成随机待排数据"<<endl;
cout<<"2.查看数据"<<endl;
cout<<"3.进行直接插入排序"<<endl;
cout<<"4.冒泡排序"<<endl;
cout<<"5.快速排序"<<endl;
cout<<"6.销毁数据"<<endl;
cout<<"——————————————————————"<<endl;
cin>>input;
do
{
switch(input)
{
case(1):
{
init(L);
Create_raw_data(L);
break;
}
case(2):
{
show(L);
cout<<""<<endl;
break;
}
case(3):
{
InsertSort(L);
break;
}
case(4):
{
Bubblesort(L);
break;
}
case(5):
{
Quicksort(L);
break;
}
case(6):
{
destroydata(L);
break;
}
}
cout<<"——————————————————————"<<endl;
cout<<"1.生成随机待排数据"<<endl;
cout<<"2.查看数据"<<endl;
cout<<"3.进行直接插入排序"<<endl;
cout<<"4.冒泡排序"<<endl;
cout<<"5.快速排序"<<endl;
cout<<"6.销毁数据"<<endl;
cout<<"——————————————————————"<<endl;
cin>>input;
}while(input!=-1);
}
运行截图:
二叉排序树:
头文件和结构体定义:
#include<iostream>
using namespace std;
typedef int elemtype;
typedef struct Bsnode{
elemtype data;
struct Bsnode* lchild;
struct Bsnode* rchild;
}Bsnode;
typedef Bsnode* Bstree;
函数定义:
void InsertBST(Bstree &T,elemtype e){ //当二叉排序树中不存在关键字等于e的数据元素时,就插入该元素
Bstree s;
if(!T){
s=new Bsnode;
s->data=e;
s->lchild=NULL;
s->rchild=NULL;
T=s;
}
else if(e<T->data)
InsertBST(T->lchild,e);
else if(e>T->data)
InsertBST(T->rchild,e);
}
void CreateBST(Bstree &T){
int e;
T=NULL;
cout<<"请输入二叉排序树的内容,输入1024时结束"<<" ";
cin>>e;
while(e!=1024){
InsertBST(T,e);
cin>>e;
}
}
void printBTS(Bstree T){ //输出二叉排序树的内容
if(T){
printBTS(T->lchild);
cout<<T->data<<" ";
printBTS(T->rchild);
}
}
main函数定义:
#include"comdef.h"
#include"app.h"
int main(){
int input;
Bstree T;
cout<<"\t1.创建二叉排序树"<<endl;
cout<<"\t2.为二叉排序树插入一个节点"<<endl;
cout<<"\t3.输出二叉排序树的数据序列"<<endl;
cout<<"\t-1.退出程序"<<endl;
cout<<"----------------------------------------------------"<<endl;
cout<<"您的选择是:"<<"" ;
cin>>input;
do
{
switch(input)
{
case(1):
{
CreateBST(T);
break;
}
case(2):
{
elemtype e;
cout<<"请输入插入的数据值"<<" ";
cin>>e;
InsertBST(T,e);
break;
}
case(3):
{
printBTS(T);
cout<<endl;
break;
}
}
cout<<"\t1.创建二叉排序树"<<endl;
cout<<"\t2.为二叉排序树插入一个节点"<<endl;
cout<<"\t3.输出二叉排序树的数据序列"<<endl;
cout<<"\t-1.退出程序"<<endl;
cout<<"----------------------------------------------------"<<endl;
cout<<"您的选择是:"<<"" ;
cin>>input;
}while(input!=-1);
}
运行截图: