program 2-1 sqlist
#include<iostream>
using namespace std;
#define Maxsize 100 //最大空间
typedef struct{
int *elem;
int length; // 顺序表的长度
}SqList;
bool InitList(SqList &L) //构造一个空的顺序表L
{ //L加&表示引用类型参数,函数内部的改变跳出函数仍然有效
//不加&内部改变,跳出函数后无效
L.elem=new int[Maxsize]; //为顺序表分配Maxsize个空间
if(!L.elem) return false; //存储分配失败
L.length=0; //空表长度为0
return true;
}
bool CreateList(SqList &L) //创建一个顺序表L
{ //L加&表示引用类型参数,函数内部的改变跳出函数仍然有效
//不加&内部改变,跳出函数后无效
int x,i=0;
cin>>x;
while(x!=-1)//输入-1时结束,也可以设置其它结束条件
{
if(L.length==Maxsize)
{
cout<<"顺序表已满!";
return false;
}
L.elem[i++]=x; //将数据存入第i个位置,然后i++
L.length++; //顺序表长度增1
cin>>x; //输入一个数据元素
}
return true;
}
bool GetElem(SqList L,int i,int &e)
{
if(i<1||i>L.length) return false;
//判断i值是否合理,若不合理,返回false
e=L.elem[i-1]; //第i-1的单元存储着第i个数据
return true;
}
int LocateELem(SqList L,int x)
{
for(int i=0;i<L.length;i++)
if(L.elem[i]==x)
return i+1; //第几个元素,例如第5个元素,下标其实为4
return -1;
}
bool ListInsert_Sq(SqList &L,int i,int e)
{
if(i<1||i>L.length+1) return false; //i值不合法
if(L.length==Maxsize) return false; //存储空间已满
for(int j=L.length-1;j>=i-1;j--)
L.elem[j+1]=L.elem[j]; //从最后一个元素开始后移,直到第i个元素后移
L.elem[i-1]=e; //将新元素e放入第i个位置
L.length++; //表长增1
return true;
}
bool ListDelete_Sq(SqList &L,int i,int &e)
{
if((i<1)||(i>L.length)) return false; //i值不合法
e=L.elem[i-1]; //将欲删除的元素保留在e中
for (int j=i;j<=L.length-1;j++)
L.elem[j-1]=L.elem[j]; //被删除元素之后的元素前移
L.length--; //表长减1
return true;
}
void print(SqList L)
{
cout<<"输出顺序表"<<endl;
for(int j=0;j<=L.length-1;j++)
cout<<L.elem[j]<<" ";
cout<<endl;
}
void DestroyList(SqList &L)
{
if (L.elem) delete []L.elem; //释放存储空间
}
int main()
{
SqList myL;
int i,e,x;
cout << "1. 初始化\n";
cout << "2. 创建\n";
cout << "3. 取值\n";
cout << "4. 查找\n";
cout << "5. 插入\n";
cout << "6. 删除\n";
cout << "7. 输出\n";
cout << "8. 销毁\n";
cout << "0. 退出\n";
int choose=-1;
while(choose!= 0)
{
cout<<"请选择:";
cin>>choose;
switch(choose)
{
case 1://初始化顺序表
cout<<"顺序表初始化..."<<endl;
if(InitList(myL))
cout<<"顺序表初始化成功!"<<endl;
else
cout<<"顺序表初始化失败!"<<endl;
break;
case 2://创建顺序表
cout<<"顺序表创建..."<<endl;
cout<<"输入整型数,输入-1结束"<<endl;
if(CreateList(myL))
cout<<"顺序表创建成功!"<<endl;
else
cout<<"顺序表创建失败!"<<endl;
break;
case 3://取值
cout<<"输入整型数i,取第i个元素输出"<<endl;
cin>>i;
if(GetElem(myL,i,e))
cout<<"第i个元素是: "<<e<<endl;
else
cout<<"顺序表取值失败!"<<endl;;
cout<<"第i个元素是: "<<e<<endl;
break;
case 4://查找
cout << "请输入要查找的数x:";
cin>>x;
if(LocateELem(myL,x)==-1)
cout<<"查找失败!"<<endl;
else
cout<<"查找成功!"<<endl;
break;
case 5://插入
cout<<"请输入要插入的位置和要插入的数据元素e:";
cin>>i>>e;
if(ListInsert_Sq(myL,i,e))
cout<<"插入成功!"<< endl;
else
cout<<"插入失败!"<<endl;
break;
case 6://删除
cout<<"请输入要删除的位置i:";
cin>>i;
if(ListDelete_Sq(myL,i,e))
cout<<" 删除成功!"<<endl;
else
cout<<"删除失败!"<<endl;
break;
case 7://输出
print(myL);
break;
case 8://销毁
cout<<"顺序表销毁..."<<endl;
DestroyList(myL);
break;
}
}
return 0;
}
program 2-2 linklist
#include<iostream>
using namespace std;
typedef struct LNode{
int data; //结点的数据域
struct LNode *next; //结点的指针域
}LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
bool InitList_L(LinkList &L)//构造一个空的单链表L
{
L=new LNode; //生成新结点作为头结点,用头指针L指向头结点
if(!L)
return false; //生成结点失败
L->next=NULL; //头结点的指针域置空
return true;
}
void CreateList_H(LinkList &L)//前插法创建单链表
{
//输入n个元素的值,建立到头结点的单链表L
int n;
LinkList s; //定义一个指针变量
L=new LNode;
L->next=NULL; //先建立一个带头结点的空链表
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout<<"请依次输入n个元素:"<<endl;
cout<<"前插法创建单链表..."<<endl;
while(n--)
{
s=new LNode; //生成新结点s
cin>>s->data; //输入元素值赋给新结点的数据域
s->next=L->next;
L->next=s; //将新结点s插入到头结点之后
}
}
void CreateList_R(LinkList &L)//尾插法创建单链表
{
//输入n个元素的值,建立带表头结点的单链表L
int n;
LinkList s, r;
L=new LNode;
L->next=NULL; //先建立一个带头结点的空链表
r=L; //尾指针r指向头结点
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout<<"请依次输入n个元素:"<<endl;
cout<<"尾插法创建单链表..."<<endl;
while(n--)
{
s=new LNode;//生成新结点
cin>>s->data; //输入元素值赋给新结点的数据域
s->next=NULL;
r->next=s;//将新结点s插入尾结点*r之后
r=s;//r指向新的尾结点s
}
}
bool GetElem_L(LinkList L,int i,int &e)//单链表的取值
{
//在带头结点的单链表L中查找第i个元素
//用e记录L中第i个数据元素的值
int j;
LinkList p;
p=L->next;//p指向第一个结点,
j=1; //j为计数器
while(j<i&&p) //顺链域向后扫描,直到p指向第i个元素或p为空
{
p=p->next; //p指向下一个结点
j++; //计数器j相应加1
}
if(!p||j>i)
return false; //i值不合法i>n或i<=0
e=p->data; //取第i个结点的数据域
return true;
}
bool LocateElem_L(LinkList L, int e) //按值查找
{
//在带头结点的单链表L中查找值为e的元素
LinkList p;
p=L->next;
while(p&&p->data!=e)//顺链域向后扫描,直到p为空或p所指结点的数据域等于e
p=p->next; //p指向下一个结点
if(!p)
return false; //查找失败p为NULL
return true;
}
bool ListInsert_L(LinkList &L,int i,int &e)//单链表的插入
{
//在带头结点的单链表L中第i个位置插入值为e的新结点
int j;
LinkList p,s;
p=L;
j=0;
while(p&&j<i-1) //查找第i-1个结点,p指向该结点
{
p=p->next;
j++;
}
if(!p||j>i-1)//i>n+1或者i<1
return false;
s=new LNode; //生成新结点
s->data=e; //将新结点的数据域置为e
s->next=p->next; //将新结点的指针域指向结点ai
p->next=s; //将结点p的指针域指向结点s
return true;
}
bool ListDelete_L(LinkList &L,int i) //单链表的删除
{
//在带头结点的单链表L中,删除第i个位置
LinkList p, q;
int j;
p=L;
j=0;
while((p->next)&&(j<i-1)) //查找第i?1个结点,p指向该结点
{
p=p->next;
j++;
}
if(!(p->next)||(j>i-1))//当i>n或i<1时,删除位置不合理
return false;
q=p->next; //临时保存被删结点的地址以备释放空间
p->next=q->next; //改变删除结点前驱结点的指针域
delete q; //释放被删除结点的空间
return true;
}
void Listprint_L(LinkList L) //单链表的输出
{
LinkList p;
p=L->next;
while(p)
{
cout<<p->data<<"\t";
p=p->next;
}
cout<<endl;
}
int main()
{
int i,x,e,choose;
LinkList L;
cout<<"1. 初始化\n";
cout<<"2. 创建单链表(前插法)\n";
cout<<"3. 创建单链表(尾插法)\n";
cout<<"4. 取值\n";
cout<<"5. 查找\n";
cout<<"6. 插入\n";
cout<<"7. 删除\n";
cout<<"8. 输出\n";
cout<<"0. 退出\n";
choose=-1;
while(choose!=0)
{
cout<<"请输入数字选择:";
cin>>choose;
switch(choose)
{
case 1: //初始化一个空的单链表
if(InitList_L(L))
cout<<"初始化一个空的单链表!\n";
break;
case 2: //创建单链表(前插法)
CreateList_H(L);
cout<<"前插法创建单链表输出结果:\n";
Listprint_L(L);
break;
case 3: //创建单链表(尾插法)
CreateList_R(L);
cout<<"尾插法创建单链表输出结果:\n";
Listprint_L(L);
break;
case 4: //单链表的按序号取值
cout<<"请输入一个位置i用来取值:";
cin>>i;
if(GetElem_L(L,i,e))
{
cout<<"查找成功\n";
cout<<"第"<<i<<"个元素是:"<<e<<endl;
}
else
cout<<"查找失败\n\n";
break;
case 5: //单链表的按值查找
cout<<"请输入所要查找元素x:";
cin>>x;
if(LocateElem_L(L,x))
cout<<"查找成功\n";
else
cout<<"查找失败! "<<endl;
break;
case 6: //单链表的插入
cout<<"请输入插入的位置和元素(用空格隔开):";
cin>>i;
cin>>x;
if(ListInsert_L(L,i,x))
cout<<"插入成功.\n\n";
else
cout<<"插入失败!\n\n";
break;
case 7: //单链表的删除
cout<<"请输入所要删除的元素位置i:";
cin>>i;
if(ListDelete_L(L, i))
cout<<"删除成功!\n";
else
cout<<"删除失败!\n";
break;
case 8: //单链表的输出
cout<<"当前单链表的数据元素分别为:\n";
Listprint_L(L);
cout<<endl;
break;
}
}
return 0;
}
program 2-3 Dulinklist
#include<iostream>
using namespace std;
typedef struct DuLNode{
int data; //结点的数据域
struct DuLNode *prior,*next; //结点的指针域
}DuLNode,*DuLinkList; //LinkList为指向结构体LNode的指针类型
bool InitDuList_L(DuLinkList &L)//构造一个空的双向链表L
{
L=new DuLNode; //生成新结点作为头结点,用头指针L指向头结点
if(!L)
return false; //生成结点失败
L->prior=L->next=NULL; //头结点的两个指针域置空
return true;
}
void CreateDuList_H(DuLinkList &L)//头插法创建双向链表
{
//输入n个元素的值,建立带头结点的双向链表L
int n;
DuLinkList s; //定义一个指针变量
L=new DuLNode;
L->prior=L->next=NULL; //先建立一个带头结点的空链表
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout<<"请依次输入n个元素:"<<endl;
cout<<"头插法创建双向链表..."<<endl;
while(n--)
{
s=new DuLNode; //生成新结点s
cin>>s->data; //输入元素值赋给新结点的数据域
if(L->next)
L->next->prior=s;
s->next=L->next;
s->prior=L;
L->next=s; //将新结点s插入到头结点之后
}
}
bool GetElem_L(DuLinkList L,int i,int &e)//双向链表的取值
{
//在带头结点的双向链表L中查找第i个元素
//用e记录L中第i个数据元素的值
int j;
DuLinkList p;
p=L->next;//p指向第一个结点,
j=1; //j为计数器
while(j<i&&p) //顺链域向后扫描,直到p指向第i个元素或p为空
{
p=p->next; //p指向下一个结点
j++; //计数器j相应加1
}
if(!p||j>i)
return false; //i值不合法i>n或i<=0
e=p->data; //取第i个结点的数据域
return true;
}
bool LocateElem_L(DuLinkList L,int e) //按值查找
{
//在带头结点的双向链表L中查找值为e的元素
DuLinkList p;
p=L->next;
while(p&&p->data!=e)//顺链域向后扫描,直到p为空或p所指结点的数据域等于e
p=p->next; //p指向下一个结点
if(!p)
return false; //查找失败p为NULL
return true;
}
bool ListInsert_L(DuLinkList &L,int i,int &e)//双向链表的插入
{
//在带头结点的单链表L中第i个位置之前插入值为e的新结点
int j;
DuLinkList p, s;
p=L;
j=0;
while(p&&j<i) //查找第i个结点,p指向该结点
{
p=p->next;
j++;
}
if(!p||j>i)//i>n+1或者i<1
return false;
s=new DuLNode; //生成新结点
s->data=e; //将新结点的数据域置为e
p->prior->next=s;
s->prior=p->prior;
s->next=p;
p->prior=s;
return true;
}
bool ListDelete_L(DuLinkList &L,int i) //双向链表的删除
{
//在带头结点的双向链表L中,删除第i个位置
DuLinkList p;
int j;
p=L;
j=0;
while(p&&(j<i)) //查找第i个结点,p指向该结点
{
p=p->next;
j++;
}
if(!p||(j>i))//当i>n或i<1时,删除位置不合理
return false;
if(p->next) //如果p的直接后继结点存在
p->next->prior=p->prior;
p->prior->next=p->next;
delete p; //释放被删除结点的空间
return true;
}
void Listprint_L(DuLinkList L) //双向链表的输出
{
DuLinkList p;
p=L->next;
while(p)
{
cout<<p->data<<"\t";
p=p->next;
}
cout<<endl;
}
int main()
{
int i,x,e,choose;
DuLinkList L;
choose=-1;
while(choose!=0)
{
cout<<"1. 初始化\n";
cout<<"2. 创建双向链表(前插法)\n";
cout<<"3. 取值\n";
cout<<"4. 查找\n";
cout<<"5. 插入\n";
cout<<"6. 删除\n";
cout<<"7. 输出\n";
cout<<"0. 退出\n";
cout<<"请输入数字选择:";
cin>>choose;
switch (choose)
{
case 1: //初始化一个空的双向链表
if(InitDuList_L(L))
cout<<"初始化一个空的双向链表!\n";
break;
case 2: //创建双向链表(前插法)
CreateDuList_H(L);
cout<<"前插法创建双向链表输出结果:\n";
Listprint_L(L);
break;
case 3: //双向链表的按序号取值
cout<<"请输入一个位置i用来取值:";
cin>>i;
if(GetElem_L(L,i,e))
{
cout<<"查找成功\n";
cout<<"第"<<i<<"个元素是:"<<e<<endl;
}
else
cout<<"查找失败\n\n";
break;
case 4: //双向链表的按值查找
cout<<"请输入所要查找元素x:";
cin>>x;
if (LocateElem_L(L,x))
cout<<"查找成功\n";
else
cout<<"查找失败! "<<endl;
break;
case 5: //双向链表的插入
cout<<"请输入插入的位置和元素(用空格隔开):";
cin>>i;
cin>>x;
if(ListInsert_L(L, i, x))
cout<<"插入成功.\n\n";
else
cout<<"插入失败!\n\n";
break;
case 6: //双向链表的删除
cout<<"请输入所要删除的元素位置i:";
cin>>i;
if (ListDelete_L(L, i))
cout<<"删除成功!\n";
else
cout<<"删除失败!\n";
break;
case 7: //双向链表的输出
cout<<"当前双向链表的数据元素分别为:\n";
Listprint_L(L);
cout<<endl;
break;
}
}
return 0;
}
program 2-5-1 mergesqlist
#include<iostream>
#include"sqlist.h"//引入自定义头文件,源码目录下名为sqlist.h的文件
using namespace std;
void MergeSqlist(SqList La,SqList Lb,SqList &Lc)//顺序有序表的合并
{
//已知顺序有序表La和Lb的元素按值非递减排列
//La和Lb合并得到新的顺序有序表Lc,Lc的元素也按值非递减排列
int i,j,k;
i=j=k=0;
Lc.length=La.length+Lb.length; //新表长度为待合并两表的长度之和
Lc.elem=new int[Lc.length]; //为合并后的新表分配一段空间
while(i<La.length&&j<Lb.length) //两个表都非空
{
if(La.elem[i]<=Lb.elem[j]) //依次取出两表中值较小放入到Lc表中
Lc.elem[k++]=La.elem[i++];
else
Lc.elem[k++]=Lb.elem[j++];
}
while(i<La.length) //La有剩余,依次将La的剩余元素插入Lc表的最后
Lc.elem[k++]=La.elem[i++];
while(j<Lb.length) //Lb有剩余,依次将Lb的剩余元素插入Lc表的最后
Lc.elem[k++]=Lb.elem[j++];
}
bool CreateList(SqList &L) //创建一个顺序表L
{ //L加&表示引用类型参数,函数内部的改变跳出函数仍然有效
//不加&内部改变,跳出函数后无效
int a,i=1;
cin>>a;
while(a!=-1)
{
ListInsert_Sq(L,i,a);
cin>>a;
i++;
}
return true;
}
void print(SqList L)
{
cout<<"输出顺序表"<<endl;
for(int j=0;j<=L.length-1;j++)
cout<<L.elem[j]<<" ";
cout<<endl;
}
int main()
{
SqList La, Lb, Lc;
cout<<"创建有序(非递减)顺序表La:"<<endl;
InitList(La); //La表的创建
CreateList(La); //依次往顺序表La里输入数据
print(La);
cout<<"创建有序(非递减)顺序表Lb:"<<endl;
InitList(Lb); //Lb表的创建
CreateList(Lb); //依次往顺序表Lb里输入数据
print(Lb);
MergeSqlist(La, Lb, Lc); //将顺序表La和Lb进行合并
cout<<"非递减线性表La,Lb合并后的非递减线性表lc为:\n"; //输出合并后的有序顺序表Lc
print(Lc);
cout<<endl;
return 0;
}
program 2-5-2 mergelinklist
#include<iostream>
using namespace std;
typedef struct LNode{
int data; //结点的数据域
struct LNode *next; //结点的指针域
}LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
bool InitList_L(LinkList &L)//构造一个空的单链表L
{
L=new LNode; //生成新结点作为头结点,用头指针L指向头结点
if(!L)
return false; //生成结点失败
L->next=NULL; //头结点的指针域置空
return true;
}
void CreateList_R(LinkList &L)//尾插法创建单链表
{
//输入n个元素的值,建立带表头结点的单链表L
int n;
LinkList s, r;
L=new LNode;
L->next=NULL; //先建立一个带头结点的空链表
r=L; //尾指针r指向头结点
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout<<"请依次输入n个整型数(非递减):" <<endl;
cout<<"尾插法创建单链表..."<<endl;
while(n--)
{
s=new LNode;//生成新结点
cin>>s->data; //输入元素值赋给新结点的数据域
s->next=NULL;
r->next=s;//将新结点s插入尾结点r之后
r=s;//r指向新的尾结点s
}
}
void mergelinklist(LinkList La,LinkList Lb,LinkList &Lc)
{
LinkList p,q,r;
p=La->next; //p指向La的第一个元素
q=Lb->next; //q指向Lb的第一个元素
Lc=La; //Lc指向La的头结点
r=Lc; //r指向Lc的尾部
while(p&&q)
{
if(p->data<=q->data)//把p指向的结点串起来
{
r->next=p;
r=p;
p=p->next;
}
else //把q指向的结点串起来
{
r->next=q;
r=q;
q=q->next;
}
}
r->next=p?p:q;//相当于if(p) r->next=p; else r->next=q;
delete Lb;
}
void Listprint_L(LinkList L) //单链表的输出
{
LinkList p;
p=L->next;
while(p)
{
cout <<p->data <<"\t";
p=p->next;
}
cout<<endl;
}
int main()
{
LinkList La,Lb,Lc;
cout<<"创建有序(非递减)单链表La:"<<endl;
InitList_L(La);
CreateList_R(La);
cout<<"创建有序(非递减)单链表Lb:"<<endl;
InitList_L(Lb);
CreateList_R(Lb);
cout<<"将两个有序(非递减)单链表La和Lb合并为Lc:"<<endl;
mergelinklist(La,Lb,Lc);
cout<<"合并后的结果Lc:"<<endl;
Listprint_L(Lc);
return 0;
}
program 2-5-3 reverselinklist
#include<iostream>
using namespace std;
typedef struct LNode{
int data; //结点的数据域
struct LNode *next; //结点的指针域
}LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
bool InitList_L(LinkList &L)//构造一个空的单链表L
{
L=new LNode; //生成新结点作为头结点,用头指针L指向头结点
if(!L)
return false; //生成结点失败
L->next=NULL; //头结点的指针域置空
return true;
}
void CreateList_R(LinkList &L)//尾插法创建单链表
{
//输入n个元素的值,建立带表头结点的单链表L
int n;
LinkList s, r;
L=new LNode;
L->next=NULL; //先建立一个带头结点的空链表
r=L; //尾指针r指向头结点
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout <<"尾插法(正序)创建单链表..." <<endl;
while(n--)
{
s=new LNode;//生成新结点
cin>>s->data; //输入元素值赋给新结点的数据域
s->next=NULL;
r->next=s;//将新结点s插入尾结点r之后
r=s;//r指向新的尾结点s
}
}
void reverselinklist(LinkList &L)
{
LinkList p,q;
p=L->next; //p指向L的第一个元素
L->next=NULL; //头结点的next域置空:
while(p)
{
q=p->next;//q指向p的下一个结点,记录断点;
p->next=L->next; //头插法,将L的下一个结点地址赋值给p的next域
L->next=p; //将p结点地址赋值给L的next域
p=q;//指针后移,p指向q;
}
}
void Listprint_L(LinkList L) //单链表的输出
{
LinkList p;
p=L->next;
while (p)
{
cout<<p->data <<"\t";
p=p->next;
}
cout<<endl;
}
int main()
{
LinkList L;
cout<<"创建单链表L:"<<endl;
InitList_L(L);
CreateList_R(L);
cout<<"单链表数据为:"<<endl;
Listprint_L(L);
cout<<"单链表就地逆置后结果为:"<<endl;
reverselinklist(L);
Listprint_L(L);
return 0;
}
program 2-5-4 findmiddle
#include<iostream>
using namespace std;
typedef struct LNode{
int data; //结点的数据域
struct LNode *next; //结点的指针域
}LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
bool InitList_L(LinkList &L)//构造一个空的单链表L
{
L=new LNode; //生成新结点作为头结点,用头指针L指向头结点
if(!L)
return false; //生成结点失败
L->next=NULL; //头结点的指针域置空
return true;
}
void CreateList_R(LinkList &L)//尾插法创建单链表
{
//输入n个元素的值,建立带表头结点的单链表L
int n;
LinkList s, r;
L=new LNode;
L->next=NULL; //先建立一个带头结点的空链表
r=L; //尾指针r指向头结点
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout<<"尾插法(正序)创建单链表..."<<endl;
while(n--)
{
s=new LNode;//生成新结点
cin>>s->data; //输入元素值赋给新结点的数据域
s->next=NULL;
r->next=s;//将新结点s插入尾结点r之后
r=s;//r指向新的尾结点s
}
}
LinkList findmiddle(LinkList L)
{
LinkList p,q;
p=L; //p为快指针,初始时指向L
q=L; //q为慢指针,初始时指向L
while(p!=NULL&&p->next!=NULL)
{
p=p->next->next;//p为快指针一次走两步;
q=q->next; //q为慢指针一次走一步
}
return q;//返回中间结点指针
}
void Listprint_L(LinkList L) //单链表的输出
{
LinkList p;
p=L->next;
while(p)
{
cout<<p->data<<"\t";
p=p->next;
}
cout<<endl;
}
int main()
{
LinkList L,mid;
cout<<"创建单链表L:"<<endl;
InitList_L(L);
CreateList_R(L);
cout<<"单链表数据为:"<<endl;
Listprint_L(L);
mid=findmiddle(L);
cout<<"单链表中间结点数据为:"<<mid->data<<endl;
return 0;
}
program 2-5-4-2 findk
#include<iostream>
using namespace std;
typedef struct LNode{
int data; //结点的数据域
struct LNode *next; //结点的指针域
}LNode,*LinkList; //LinkList为指向结构体LNode的指针类型
bool InitList_L(LinkList &L)//构造一个空的单链表L
{
L=new LNode; //生成新结点作为头结点,用头指针L指向头结点
if(!L)
return false; //生成结点失败
L->next=NULL; //头结点的指针域置空
return true;
}
void CreateList_R(LinkList &L)//尾插法创建单链表
{
//输入n个元素的值,建立带表头结点的单链表L
int n;
LinkList s, r;
L=new LNode;
L->next=NULL; //先建立一个带头结点的空链表
r=L; //尾指针r指向头结点
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout<<"尾插法(正序)创建单链表..."<<endl;
while(n--)
{
s=new LNode;//生成新结点
cin>>s->data; //输入元素值赋给新结点的数据域
s->next=NULL;
r->next=s;//将新结点s插入尾结点r之后
r=s;//r指向新的尾结点s
}
}
LinkList findk(LinkList L,int k)
{
LinkList p,q;
p=L->next; //p为快指针,初始时指向第一个数据结点
q=L->next; //q为慢指针,初始时指向第一个数据结点
while(p->next!=NULL)
{
if(--k<=0)
q=q->next;//q为慢指针
p=p->next; //p为快指针;
}
if(k>0)
return NULL;
else
return q;//返回中间结点指针
}
void Listprint_L(LinkList L) //单链表的输出
{
LinkList p;
p=L->next;
while(p)
{
cout<<p->data<<"\t";
p=p->next;
}
cout<<endl;
}
int main()
{
LinkList L,r;
int k;
cout<<"创建单链表L:"<<endl;
InitList_L(L);
CreateList_R(L);
cout<<"单链表数据为:"<<endl;
Listprint_L(L);
cout<<"需要查找倒数第k个结点的k值:"<<endl;
cin>>k;
r=findk(L,k);
if(r)
cout<<"单链表倒数第"<<k<<"个结点数据为:"<<r->data<<endl;
else
cout<<"没找到倒数第"<<k<<"个结点!"<<endl;
return 0;
}
program 2-5-5 deleterep
#include<iostream>
#include<algorithm>//abs()求绝对值函数需要此头文件
using namespace std;
typedef struct LNode{
int data; //结点的数据域
struct LNode *next; //结点的指针域
}LNode, *LinkList; //LinkList为指向结构体LNode的指针类型
int m,n;
bool InitList_L(LinkList &L)//构造一个空的单链表L
{
L=new LNode; //生成新结点作为头结点,用头指针L指向头结点
if(!L)
return false; //生成结点失败
L->next=NULL; //头结点的指针域置空
return true;
}
void CreateList_R(LinkList &L)//尾插法创建单链表
{
//输入n个元素的值,建立带表头结点的单链表L
LinkList s, r;
L=new LNode;
L->next=NULL; //先建立一个带头结点的空链表
r=L; //尾指针r指向头结点
cout<<"请输入元素个数m,数据元素的范围n:"<<endl;
cin>>m>>n;
cout<<"输入m个绝对值不超过n的整数..."<<endl;
while(m--)
{
s=new LNode;//生成新结点
cin>>s->data; //输入元素值赋给新结点的数据域
s->next=NULL;
r->next=s;//将新结点s插入尾结点r之后
r=s;//r指向新的尾结点s
}
}
void Deleterep(LinkList &L)//删除重复元素
{
LinkList p,q;
int x;
int *flag=new int[n+1]; //定义flag数组,分配n+1个空间
for(int i=0;i<n+1;i++) //初始化
flag[i]=0;
p=L; //指向头结点
while(p->next!=NULL)
{
x=abs(p->next->data);
if(flag[x]==0)//未出现过
{
flag[x]=1; //标记出现
p=p->next; //指针后移
}
else
{
q=p->next;
p->next=q->next;//删除重复元素
delete q;
}
}
delete []flag;
}
void Listprint_L(LinkList L) //单链表的输出
{
LinkList p;
p=L->next;
while(p)
{
cout<<p->data<<"\t";
p=p->next;
}
cout<<endl;
}
int main()
{
LinkList L;
cout<<"创建单链表L:"<<endl;
InitList_L(L);
CreateList_R(L);
cout<<"单链表数据为:"<<endl;
Listprint_L(L);
cout<<"删除重复元素:"<<endl;
Deleterep(L);
Listprint_L(L);
return 0;
}
program 3-1 sqstack
#include<iostream>
using namespace std;
#define Maxsize 100 //预先分配空间,这个数值根据实际需要预估确定;
typedef struct SqStack {
int *base; //栈底指针
int *top; //栈顶指针
}SqStack;
bool InitStack(SqStack &S) //构造一个空栈S
{
S.base=new int[Maxsize];//为顺序栈分配一个最大容量为Maxsize的空间
if(!S.base) //空间分配失败
return false;
S.top=S.base; //top初始为base,空栈
return true;
}
bool Push(SqStack &S,int e) // 插入元素e为新的栈顶元素
{
if(S.top-S.base==Maxsize) //栈满
return false;
*(S.top++)=e; //元素e压入栈顶,然后栈顶指针加1,等价于*S.top=e; S.top++;
return true;
}
bool Pop(SqStack &S,int &e) //删除S的栈顶元素,暂存在变量e中
{
if(S.base==S.top) //栈空
return false;
e=*(--S.top); //栈顶指针减1,将栈顶元素赋给e
return true;
}
int GetTop(SqStack S) //返回S的栈顶元素,栈顶指针不变
{
if(S.top!=S.base) //栈非空
return *(S.top-1); //返回栈顶元素的值,栈顶指针不变
else
return -1;
}
int main()
{
int n,x;
SqStack S;
InitStack(S);//初始化一个顺序栈S
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout<<"请依次输入n个元素,依次入栈:"<<endl;
while(n--)
{
cin>>x; //输入元素
Push(S,x);
}
cout<<"元素依次出栈:"<<endl;
while(S.top!=S.base)//如果栈不空,则依次出栈
{
cout<<GetTop(S)<<"\t";//输出栈顶元素
Pop(S,x); //栈顶元素出栈
}
return 0;
}
program 3-2 linkstack
#include<iostream>
using namespace std;
typedef struct Snode{
int data; //数据域
struct Snode *next; //指针域
}Snode,*LinkStack;
bool InitStack(LinkStack &S)//构造一个空栈S
{
S=NULL;
return true;
}
bool Push(LinkStack &S,int e) //在栈顶插入元素e
{
LinkStack p;
p=new Snode; //生成新结点
p->data=e; //将e放在新结点数据域
p->next=S; //将新结点的指针域指向S,即将S的地址赋值给新结点的指针域
S=p; //修改栈顶指针为p
return true;
}
bool Pop(LinkStack &S,int &e) //删除S的栈顶元素,用e保存其值
{
LinkStack p;
if(S==NULL) //栈空
return false;
e=S->data; //将栈顶元素赋给e
p=S; //用p保存栈顶元素地址,以备释放
S=S->next; //修改栈顶指针,指向下一个结点
delete p; //释放原栈顶元素的空间
return true;
}
int GetTop(LinkStack S) //返回S的栈顶元素,不修改栈顶指针
{
if(S!=NULL) //栈非空
return S->data; //返回栈顶元素的值,栈顶指针不变
else
return -1;
}
int main()
{
int n,x;
LinkStack S;
InitStack(S);//初始化一个顺序栈S
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout<<"请依次输入n个元素,依次入栈:"<<endl;
while(n--)
{
cin>>x; //输入元素
Push(S,x);
}
cout<<"元素依次出栈:"<<endl;
while(S!=NULL)//如果栈不空,则依次出栈
{
cout<<GetTop(S)<<"\t";//输出栈顶元素
Pop(S,x); //栈顶元素出栈
}
return 0;
}
program 3-3 sqqueue
#include<iostream>
using namespace std;
#define Maxsize 100
typedef struct SqQueue{
int *base; //基地址
int front,rear; //头指针,尾指针
}SqQueue;
//循环队列的初始化
bool InitQueue(SqQueue &Q)//注意使用引用参数,否则出了函数,其改变无效
{
Q.base=new int[Maxsize];//分配空间
if(!Q.base) return false;
Q.front=Q.rear=0; //头指针和尾指针置为零,队列为空
return true;
}
//循环队列的入队
bool EnQueue(SqQueue &Q,int e)//将元素e放入Q的队尾
{
if((Q.rear+1)%Maxsize==Q.front) //尾指针后移一位等于头指针,表明队满
return false;
Q.base[Q.rear]=e; //新元素插入队尾
Q.rear=(Q.rear+1)%Maxsize; //队尾指针加1
return true;
}
//循环队列的出队
bool DeQueue(SqQueue &Q, int &e) //删除Q的队头元素,用e返回其值
{
if(Q.front==Q.rear)
return false; //队空
e=Q.base[Q.front]; //保存队头元素
Q.front=(Q.front+1)%Maxsize; //队头指针加1
return true;
}
//取循环队列的队头元素
int GetHead(SqQueue Q)//返回Q的队头元素,不修改队头指针
{
if(Q.front!=Q.rear) //队列非空
return Q.base[Q.front];
return -1;
}
//循环队列的长度
int QueueLength(SqQueue Q)
{
return (Q.rear-Q.front+Maxsize)%Maxsize;
}
int main()
{
SqQueue Q;
int n,x;
InitQueue(Q);//初始化队列(一定要初始化,否则后面存储出错)
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout<<"请依次输入n个整型数,依次入队:"<<endl;
while(n--)
{
cin>>x;
EnQueue(Q,x);//入队
}
cout<<endl;
cout<<"队列内元素个数,即长度:"<<QueueLength(Q)<<endl;
cout<<"队头元素:"<<GetHead(Q)<<endl;
cout<<"元素依次出队:"<<endl;
while(true)//如果栈不空,则依次出栈
{
if(DeQueue(Q,x))
cout<<x<<"\t";//出队元素
else
break;
}
cout<<endl;
cout<<"队列内元素个数,即长度:"<<QueueLength(Q)<<endl;
return 0;
}
program 3-4 linkqueue
#include<iostream>
using namespace std;
typedef struct Qnode{
int data;
struct Qnode *next;
}Qnode,*Qptr;
typedef struct{
Qnode *front;
Qnode *rear;
}LinkQueue;
//链队的初始化
void InitQueue(LinkQueue &Q)//注意使用引用参数,否则出了函数,其改变无效
{
Q.front=Q.rear=new Qnode; //创建头结点,头指针和尾指针指向头结点
Q.front->next=NULL;
}
//链队列的入队
void EnQueue(LinkQueue &Q,int e)//将元素e放入队尾
{
Qptr s;
s=new Qnode;
s->data=e;
s->next=NULL;
Q.rear->next=s;//新元素插入队尾
Q.rear=s; //队尾指针后移
}
//链队列的出队
bool DeQueue(LinkQueue &Q,int &e) //删除Q的队头元素,用e返回其值
{
Qptr p;
if(Q.front==Q.rear)//队空
return false;
p=Q.front->next;
e=p->data; //保存队头元素
Q.front->next=p->next;
if(Q.rear==p) //若队列中只有一个元素,删除后需要修改队尾指针
Q.rear=Q.front;
delete p;
return true;
}
//取循环队列的队头元素
int GetHead(LinkQueue Q)//返回Q的队头元素,不修改队头指针
{
if (Q.front!=Q.rear) //队列非空
return Q.front->next->data;
return -1;
}
int main()
{
LinkQueue Q;
int n,x;
InitQueue(Q);//初始化队列(一定要初始化,否则后面存储出错)
cout<<"请输入元素个数n:"<<endl;
cin>>n;
cout<<"请依次输入n个整型数,依次入队:"<<endl;
while(n--)
{
cin>>x;
EnQueue(Q,x);//入队
}
cout<<"队头元素:"<<GetHead(Q)<<endl;
cout<<"元素依次出队:"<<endl;
while(true)//如果栈不空,则依次出栈
{
if(DeQueue(Q,x))
cout<<x<<"\t";//出队元素
else
break;
}
cout<<endl;
return 0;
}
program 3-5-1 binaryconversion
#include<iostream>
typedef int Elemtype;//先类型定义为int
#include"sqstack.h"//引入自定义头文件,源码目录下名为sqstack.h的文件
using namespace std;
void binaryconversion(int n){
SqStack S;//定义一个栈S
int e;
InitStack(S);//初始化栈
while(n){
Push(S,n%2);
n=n/2;
}
while(!Empty(S)){//如果栈不空
Pop(S,e);//出栈
cout<<e<<"\t";//输出栈顶元素
}
}
int main(){
int n;
cout<<"请输入一个大于0的十进制整数:"<<endl;
cin>>n;
binaryconversion(n);
return 0;
}
program 3-5-2 palindrome
#include<iostream>
#include<cstring>
typedef char Elemtype;//先类型定义为char
#include"sqstack.h"//引入自定义头文件,源码目录下名为sqstack.h的文件
using namespace std;
bool palindrome(char *str){//判断字符串是否为回文
SqStack S;//定义一个栈S
int len,i;
char e;
len=strlen(str);//返回字符串长度
InitStack(S);//初始化栈
for(i=0;i<len/2;i++)//将字符串前一半依次入栈
Push(S,str[i]);
if(len%2==1)//字符串长度为奇数,跳过中心点
i++;
while(!Empty(S)){//如果栈不空
Pop(S,e);//出栈
if(e!=str[i])//比较元素是否相等
return false;
else
i++;
}
return true;
}
int main(){
char str[20];
cout<<"请输入一个长度小于20的字符串:"<<endl;
cin>>str;
if(palindrome(str))
cout<<"该字符串是回文!"<<endl;
else
cout<<"该字符串不是回文!"<<endl;
return 0;
}
program 3-5-3 duqueue
#include<iostream>
using namespace std;
#define Maxsize 100
typedef char ElemType;
typedef struct SqQueue{
ElemType base[Maxsize]; //一维数组存储,也可以设置指针动态分配空间
int front,rear; //头指针,尾指针
}DuQueue;
//初始化
void InitQueue(DuQueue &Q)//注意使用引用参数,否则出了函数,其改变无效
{
Q.front=Q.rear=0; //头指针和尾指针置为零,队列为空
}
//判队空
bool isEmpty(DuQueue Q)
{
if(Q.front==Q.rear)
return true;
else
return false;
}
//判队满
bool isFull(DuQueue Q)
{
if((Q.rear+1)%Maxsize==Q.front) //尾指针后移一位等于头指针,表明队满
return true;
else
return false;
}
//头进
bool push_front(DuQueue &Q,ElemType e)
{
if(isFull(Q))
return false;
Q.front=(Q.front-1+Maxsize)%Maxsize;//先向前移动一位
Q.base[Q.front]=e; //后放入
return true;
}
//头出
bool pop_front(DuQueue &Q,ElemType &x)
{
if(isEmpty(Q))
return false;
x=Q.base[Q.front]; //取数据
Q.front=(Q.front+1)%Maxsize;//向后移动一位
return true;
}
//尾进
bool push_back(DuQueue &Q,ElemType e)
{
if(isFull(Q))
return false;
Q.base[Q.rear]=e; //先放入
Q.rear=(Q.rear+1)%Maxsize;//向后移动一位
return true;
}
//尾出
bool pop_back(DuQueue &Q,ElemType &x)
{
if(isEmpty(Q))
return false;
Q.rear=(Q.rear-1+Maxsize)%Maxsize;//向前移动一位
x=Q.base[Q.rear]; //取数据
return true;
}
//取队头
bool get_front(DuQueue Q,ElemType &x)
{
if(isEmpty(Q))
return false;
x=Q.base[Q.front]; //取队头数据;
return true;
}
//取队尾
bool get_back(DuQueue Q,ElemType &x)
{
if(isEmpty(Q))
return false;
x=Q.base[(Q.rear-1+Maxsize)%Maxsize];
return true;
}
//求长度
int length(DuQueue Q)
{
return (Q.rear-Q.front+Maxsize)%Maxsize;
}
//从头到尾输出整个队列元素(遍历)
void traverse(DuQueue Q)
{
if(isEmpty(Q))
{
cout<<"DuQueue is empty"<<endl;
return ;
}
int temp=Q.front;//设置一个暂存变量,头指针未移动
while(temp!=Q.rear)
{
cout<<Q.base[temp]<<"\t";
temp=(temp+1)%Maxsize;
}
cout<<endl<<"traverse is over!"<<endl;
}
int main()
{
DuQueue DuQ;
ElemType e,x;
cout<<"1. 初始化\n";
cout<<"2. 头进\n";
cout<<"3. 头出\n";
cout<<"4. 尾进\n";
cout<<"5. 尾出\n";
cout<<"6. 取队头\n";
cout<<"7. 取队尾\n";
cout<<"8. 求长度\n";
cout<<"9. 遍历队列\n";
cout<<"0. 退出\n";
int choose=-1;
while (choose!=0)
{
cout<<"请选择:";
cin>>choose;
switch(choose)
{
case 1://初始化
cout << "双端队列初始化..." << endl;
InitQueue(DuQ);
break;
case 2://头进
cout << "从前端进队(头进)..." << endl;
cout << "请输入一个字符:" << endl;
cin>>e;
push_front(DuQ,e);
break;
case 3://头出
cout <<"从前端出队(头出)..."<< endl;
pop_front(DuQ,x);
cout << "出队元素为" <<x<< endl;
break;
case 4://尾进
cout << "从后端进队(尾进)..." << endl;
cout << "请输入一个字符:" << endl;
cin>>e;
push_back(DuQ,e);
break;
case 5://尾出
cout <<"从后端出队(尾出)..."<< endl;
pop_back(DuQ,x);
cout << "出队元素为" <<x<< endl;
break;
case 6://取队头元素
cout <<"取队头元素..."<< endl;
get_front(DuQ,x);
cout << "队头元素为" <<x<< endl;
break;
case 7://取队尾元素
cout <<"取队尾元素..."<< endl;
get_back(DuQ,x);
cout << "队尾元素为" <<x<< endl;
break;
case 8://求队长
cout << "双端队列长度:"<<length(DuQ)<<endl;
break;
case 9://遍历
traverse(DuQ);
break;
}
}
return 0;
}
program 4-4 kmp
#include<iostream>/***KMP算法***/
#include<cstring>
using namespace std;
#define Maxsize 100
typedef char SString[Maxsize+1];//0号单元存放串的长度
bool StrAssign(SString &T,char *chars){//生成一个其值等于chars的串T
int i;
if(strlen(chars)>Maxsize)
return false;
else{
T[0]=strlen(chars);
for(i=1;i<=T[0];i++){
T[i]=*(chars+i-1);
cout<<T[i]<<" ";
}
cout<<endl;
return true;
}
}
int Index_BF(SString S,SString T,int pos){//BF算法
// 求T在主串S中第pos个字符之后第一次出现的位置
//其中,T非空,1≤pos≤s[0],s[0]存放S串的长度
int i=pos,j=1,sum=0;
while(i<=S[0]&&j<=T[0]){
sum++;
if(S[i]==T[j]){//如果相等,则继续比较后面的字符
i++;
j++;
}
else{
i=i-j+2; //i退回到上一轮开始比较的下一个字符
j=1; //j退回到第1个字符
}
}
cout<<"一共比较了"<<sum<<"次"<<endl;
if(j>T[0]) // 匹配成功
return i-T[0];
else
return 0;
}
void get_next(SString T,int next[]){//计算next函数值
int j=1,k=0;
next[1]=0;
while(j<T[0]){
if(k==0||T[j]==T[k])
next[++j]=++k;
else
k=next[k];
}
cout<<"-----next[]-------"<<endl;
for(j=1;j<=T[0];j++)
cout<<next[j]<<" ";
cout<<endl;
}
void get_next2(SString T,int next[]){//计算next函数值改进算法
int j=1,k=0;
next[1]=0;
while(j<T[0]){
if(k==0||T[j]==T[k]){
j++;
k++;
if(T[j]==T[k])
next[j]=next[k];
else
next[j]=k;
}
else
k=next[k];
}
cout<<"-----next[]-------"<<endl;
for(j=1;j<=T[0];j++)
cout<<next[j]<<" ";
cout<<endl;
}
int Index_KMP(SString S,SString T,int pos,int next[]){//KMP算法
// 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法
//其中,T非空,1≤pos≤StrLength(S)
int i=pos,j=1,sum=0;
while(i<=S[0]&&j<=T[0]){
sum++;
if(j==0||S[i]==T[j]){ // 继续比较后面的字符
i++;
j++;
}
else
j=next[j]; // 模式串向右移动
}
cout<<"一共比较了"<<sum<<"次"<<endl;
if(j>T[0]) // 匹配成功
return i-T[0];
else
return 0;
}
int main(){
SString S,T;
char str[100];
cout<<"串S:"<<" ";
cin>>str;//aabaaabaaaabea
StrAssign(S,str);//可以修改程序,自己输入字符串
cout<<"串T:"<<" ";
cin>>str;//aaaab
StrAssign(T,str);
int *p=new int[T[0]+1]; //生成T的next数组
cout<<endl;
cout<<"BF算法运行结果:"<<endl;
cout<<"主串和子串在第"<<Index_BF(S,T,1)<<"个字符处首次匹配\n";
cout<<endl;
cout<<"KMP算法运行结果:"<<endl;
get_next(T,p);
cout<<"主串和子串在第"<<Index_KMP(S,T,1,p)<<"个字符处首次匹配\n";
cout<<endl;
cout<<"改进的KMP算法运行结果:"<<endl;
get_next2(T,p);
cout<<"主串和子串在第"<<Index_KMP(S,T,1,p)<<"个字符处首次匹配\n";
return 0;
}
program 4-6 Virus_detection
#include<cstring>/***病毒检测算法***/
#include<iostream>
using namespace std;
#define Maxsize 100
typedef char SString[Maxsize+1];//0号单元存放串的长度
bool StrAssign(SString &T,char *chars){//生成一个其值等于chars的串T
int i;
if(strlen(chars)>Maxsize)
return false;
else{
T[0]=strlen(chars);//0号单元存放串的长度
for(i=1;i<=T[0];i++){
T[i]=*(chars+i-1);
cout<<T[i]<<" ";
}
cout<<endl;
return true;
}
}
void get_next(SString T,int next[]){//计算next函数值
int j=1,k=0;
next[1]=0;
while(j<T[0]){
if(k==0||T[j]==T[k])
next[++j]=++k;
else
k=next[k];
}
}
int Index_KMP(SString S,SString T,int pos){ //KMP算法
// 利用模式串T的next函数求T在主串S中第pos个字符之后的位置的KMP算法
//其中,T非空,1≤pos≤StrLength(S)
int *next=new int[T[0]+1];
get_next(T,next);//求T的next数组
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;
}
bool Virus_detection(SString S, SString T){//病毒检测
int i,j;
SString temp;//temp记录病毒变种
for(i=T[0]+1,j=1;j<=T[0];i++,j++)//将T串扩大一倍,T[0]为病毒长度
T[i]=T[j];
for(i=0;i<T[0];i++){//依次检测T[0]个病毒变种
temp[0]=T[0];病毒变种长度为T[0]
for(j=1;j<=T[0];j++)//取出一个病毒变种
temp[j]=T[i+j];
if(Index_KMP(S,temp,1))//检测到病毒
return 1;
}
return 0;
}
int main(){
SString S,T;
char str[100];
cout<<"患者DNA序列S:";
cin>>str;//eabbacab
StrAssign(S,str);
cout<<"病毒DNA序列T:";
cin>>str;//aabb
StrAssign(T,str);
if(Virus_detection(S,T))
cout<<"该患者已感染病毒!"<<endl;
else
cout<<"该患者未感染病毒!"<<endl;
return 0;
}
program 5-3 Retro Snaker
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct{
int x;
int y;
}Position;//位置
int m[30][30];//地图
Position here,next;//当前位置,下一个位置
Position DIR[4]={0,1,1,0,0,-1,-1,0};//右下左上方向数组
void Init(int n){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++) //方格阵列初始化为0
m[i][j]=0;
}
for(int j=0;j<=n+1;j++) //方格阵列上下围墙
m[0][j]=m[n+1][j]=-1;
for(int i=0;i<=n+1;i++) //方格阵列左右围墙
m[i][0]=m[i][n+1]=-1;
}
void Print(int start,int endi){//start, endi为开始和结束下标
for(int i=start;i<=endi;i++){
cout<<m[i][start];
for(int j=start+1;j<=endi;j++)
cout<<"\t"<<m[i][j];
cout<<endl;
}
cout<<endl;
}
//n:问题规模,m[][]:地图矩阵
void Solve(int n){
here.x=1;//左上角有蛋糕的位置
here.y=1;
int dirIndex=0;
int num=1;
m[1][1]=1;
while(num<n*n){
next.x=here.x+DIR[dirIndex].x;
next.y=here.y+DIR[dirIndex].y;
if(m[next.x][next.y]==0){ //判断下一个位置是否有蛋糕
m[next.x][next.y]=++num; //吃了蛋糕,拉出的数字加1
here=next; //以next为当前位置,继续走
}
else
dirIndex=(dirIndex+1)%4;//换下一个方向,按右下左上顺序继续吃蛋糕
}
}
int main(){
int n=0;
cout<<"请输入大于1小于等于20的整数n:"<<endl;
cin>>n;
while(n<1||n>20){
cout<<"请输入大于1小于等于20的整数n:"<<endl;
cin>>n;
}
Init(n);
Print(0,n+1);
Solve(n);
Print(1,n);
return 0;
}
program 6-2-3 createbtree
#include<iostream>
using namespace std;
typedef struct Bnode{ /*定义二叉树存储结构*/
char data;
struct Bnode *lchild,*rchild;
}Bnode,*Btree;
void createtree(Btree &T) /*创建二叉树函数*/
{
char check; /*判断是否创建左右孩子*/
T=new Bnode;
cout<<"请输入结点信息:"<<endl; /*输入根结点数据*/
cin>>T->data;
cout<<"是否添加 "<<T->data<<"的左孩子? (Y/N)"<<endl; /*询问是否创建T的左子树*/
cin>>check;
if(check=='Y')
createtree(T->lchild);
else
T->lchild=NULL;
cout<<"是否添加"<<T->data<<"的右孩子? (Y/N)"<<endl; /*询问是否创建T的右子树*/
cin>>check;
if(check=='Y')
createtree(T->rchild);
else
T->rchild=NULL;
return;
}
int main()
{
Btree mytree;
createtree(mytree);/*创建二叉树*/
return 0;
}
program 6-3 traverse
#include<iostream>
#include<queue>//引入队列头文件
using namespace std;
typedef struct Bnode{/*定义二叉树存储结构*/
char data;
struct Bnode *lchild,*rchild;
}Bnode,*Btree;
void Createtree(Btree &T) /*创建二叉树函数*/
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin>>ch;
if(ch=='#')
T=NULL; //递归结束,建空树
else{
T=new Bnode;
T->data=ch; //生成根结点
Createtree(T->lchild); //递归创建左子树
Createtree(T->rchild); //递归创建右子树
}
}
void preorder(Btree T)//先序遍历
{
if(T)
{
cout<<T->data<<" ";
preorder(T->lchild);
preorder(T->rchild);
}
}
void inorder(Btree T)//中序遍历
{
if(T)
{
inorder(T->lchild);
cout<<T->data<<" ";
inorder(T->rchild);
}
}
void posorder(Btree T)//后序遍历
{
if(T)
{
posorder(T->lchild);
posorder(T->rchild);
cout<<T->data<<" ";
}
}
bool Leveltraverse(Btree T)
{
Btree p;
if(!T)
return false;
queue<Btree>Q; //创建一个普通队列(先进先出),里面存放指针类型
Q.push(T); //根指针入队
while(!Q.empty()) //如果队列不空
{
p=Q.front();//取出队头元素作为当前扩展结点livenode
Q.pop(); //队头元素出队
cout<<p->data<<" ";
if(p->lchild)
Q.push(p->lchild); //左孩子指针入队
if(p->rchild)
Q.push(p->rchild); //右孩子指针入队
}
return true;
}
int main()
{
Btree mytree;
cout<<"按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树"<<endl;
Createtree(mytree);//创建二叉树
cout<<endl;
cout<<"二叉树的先序遍历结果:"<<endl;
preorder(mytree);//先序遍历二叉树
cout<<endl;
cout<<"二叉树的中序遍历结果:"<<endl;
inorder(mytree);//中序遍历二叉树
cout<<endl;
cout<<"二叉树的后序遍历结果:"<<endl;
posorder(mytree);//后序遍历二叉树
cout<<endl;
cout<<"二叉树的层次遍历结果:"<<endl;
Leveltraverse(mytree);//层次遍历二叉树
return 0;
}
program 6-4 InThread
#include<iostream>
using namespace std;
//线索二叉树的存储结点
typedef struct BTnode
{
char data; //结点数据域
struct BTnode *lchild,*rchild; //左右孩子指针
int ltag,rtag;
}BTnode,*BTtree;
//全局变量pre
BTtree pre;
//创建二叉树(补空法)
void CreateBiTree(BTtree &T)
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin>>ch;
if(ch=='#') T=NULL; //递归结束,建空树
else
{
T=new BTnode;
T->data=ch; //生成根结点
CreateBiTree(T->lchild); //递归创建左子树
CreateBiTree(T->rchild); //递归创建右子树
}
}
void InThread(BTtree &p)//中序线索化
{
//pre是全局变量,指向当前结点p的前驱
if(p)
{
InThread(p->lchild); //左子树递归线索化
if(!p->lchild) //p的左孩子为空
{
p->ltag=1; //给p加上左线索
p->lchild=pre; //p的左孩子指针指向pre(前驱)
}
else
p->ltag=0;
if(pre)
{
if(!pre->rchild) //pre的右孩子为空
{
pre->rtag=1; //给pre加上右线索
pre->rchild=p; //pre的右孩子指针指向p(后继)
}
else
pre->rtag=0;
}
pre=p; //保持pre指向p的前驱
InThread(p->rchild); //右子树递归线索化
}
}
void CreateInThread(BTtree &T)//创建中序线索二叉树
{
pre=NULL;//初始化为空
if(T)
{
InThread(T); //中序线索化
pre->rchild=NULL;// 处理遍历的最后一个结点,其后继为空
pre->rtag=1;
}
}
void Inorder(BTtree T)//中序遍历二叉树
{
if(T)
{
Inorder(T->lchild);
cout<<T->data<<" ";
Inorder(T->rchild);
}
}
void InorderThread(BTtree T)//遍历中序线索二叉树
{
BTtree p;
p=T;
while(p)
{
while(p->ltag==0) p=p->lchild; //找最左结点
cout<<p->data<<" ";//输出结点信息
while(p->rtag==1&&p->rchild) //右孩子为线索化,指向后继
{
p=p->rchild; //访问后继结点
cout<<p->data<<" ";//输出结点信息
}
p=p->rchild;//转向p的右子树
}
}
int main()
{
BTtree tree;
cout<<"请输入先序创建二叉树的序列(补空法):\n";//例如ABD##E##CF#G###
CreateBiTree(tree); //创建二叉树
cout<<"二叉树的中序遍历结果:\n";
Inorder(tree); //中序遍历二叉树
cout<<endl;
CreateInThread(tree);//创建中序线索二叉树
cout<<"中序线索二叉树的遍历结果:\n";
InorderThread(tree); //遍历中序线索二叉树
return 0;
}
program 6-6-1 Depth
#include<iostream>
using namespace std;
typedef struct Bnode /*定义二叉树存储结构*/
{ char data;
struct Bnode *lchild,*rchild;
}Bnode,*Btree;
void Createtree(Btree &T) /*创建二叉树函数*/
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin>>ch;
if(ch=='#')
T=NULL; //递归结束,建空树
else{
T=new Bnode;
T->data=ch; //生成根结点
Createtree(T->lchild); //递归创建左子树
Createtree(T->rchild); //递归创建右子树
}
}
int Depth(Btree T)//求二叉树的深度
{
int m,n;
if(T==NULL)//如果为空树,深度为0
return 0;
else
{
m=Depth(T->lchild);//递归计算左子树深度
n=Depth(T->rchild);//递归计算左子树深度
if(m>n)
return m+1;//返回左右子树最大值加1
else
return n+1;
}
}
int main()
{
Btree mytree;
cout<<"按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树"<<endl;
//ABD##E##CF#G###
Createtree(mytree);//创建二叉树
cout<<endl;
cout<<"二叉树的深度为:"<<Depth(mytree)<<endl;
return 0;
}
program 6-6-2 Leafcount
#include<iostream>
using namespace std;
typedef struct Bnode{ /*定义二叉树存储结构*/
char data;
struct Bnode *lchild,*rchild;
}Bnode,*Btree;
void Createtree(Btree &T) /*创建二叉树函数*/
{
//按先序次序输入二叉树中结点的值(一个字符),创建二叉链表表示的二叉树T
char ch;
cin>>ch;
if(ch=='#')
T=NULL; //递归结束,建空树
else{
T=new Bnode;
T->data=ch; //生成根结点
Createtree(T->lchild); //递归创建左子树
Createtree(T->rchild); //递归创建右子树
}
}
int LeafCount(Btree T)//求二叉树的叶子数
{
if(T==NULL)//如果为空树,深度为0
return 0;
else
if(T->lchild==NULL&&T->rchild==NULL)//左右子树均为空,则叶子数为1
return 1;
else
return LeafCount(T->lchild)+LeafCount(T->rchild);//递归计算左子树和右子树的叶子数之和
}
int NodeCount(Btree T)//求二叉树的结点数
{
if(T==NULL)//如果为空树,深度为0
return 0;
else
return NodeCount(T->lchild)+NodeCount(T->rchild)+1;//递归计算左子树和右子树的结点数之和加1
}
int main()
{
Btree mytree;
cout<<"按先序次序输入二叉树中结点的值(孩子为空时输入#),创建一棵二叉树"<<endl;
//ABD##E##CF#G###
Createtree(mytree);//创建二叉树
cout<<endl;
cout<<"二叉树的结点数为:"<<NodeCount(mytree)<<endl;
cout<<"二叉树的叶子数为:"<<LeafCount(mytree)<<endl;
return 0;
}
program 6-6-3 biTree
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
/*
输入三元组 (F、C、L/R) 序列输入一棵二叉树的诸边(其中 F 表示双亲结点的标识,C 表示孩子结点标识,L/R 表示 C 为 F 的左孩子或右孩子),
且在输入的三元组序列中,C 是按层次顺序出现的。
设结点的标识是字符类型。F=NULL时 C 为根结点标识,若 C 亦为NULL,则表示输入结束。
试编写算法,由输入的三元组序列建立二叉树的二叉链表,并以先序、中序、后序序列输出。
*/
/*测试数据
NULL A L
A B L
A C R
B D R
C E L
C F R
D G L
F H L
NULL NULL L
*/
struct biTnode
{
string data;
biTnode *lChild,*rChild;
};
biTnode* T=NULL;
void CreatebiTree(biTnode* &T)
{
string a,b,c;
biTnode *node,*p;
queue<biTnode*>q;
cin>>a>>b>>c;
if(a=="NULL"&&b!="NULL")//创建根结点
{
node=new biTnode;
node->data=b;
node->lChild=node->rChild=NULL;
T=node;
q.push(T);
}
cin>>a>>b>>c;
while(!q.empty()&&a!="NULL"&&b!="NULL")
{
p=q.front();
q.pop();
while(a==p->data)
{
node=new biTnode;
node->data=b;
node->lChild=node->rChild=NULL;
if(c=="L")
{
p->lChild=node;
cout<<p->data<<"'s lChild is "<<node->data<<endl;
}
else
{
p->rChild=node;
cout<<p->data<<"'s rChild is "<<node->data<<endl;
}
q.push(node);
cin>>a>>b>>c;
}
}
}
void preorder(biTnode* &T)
{
if(T)
{
cout<<T->data<<" ";
preorder(T->lChild);
preorder(T->rChild);
}
}
void inorder(biTnode* &T)
{
if(T)
{
inorder(T->lChild);
cout<<T->data<<" ";
inorder(T->rChild);
}
}
void posorder(biTnode* &T)
{
if(T)
{
posorder(T->lChild);
posorder(T->rChild);
cout<<T->data<<" ";
}
}
int main()
{
cout<<"输入结点数据a,b,c(a为父亲,b为结点字符,c为‘L’左孩子或‘R’右孩子)"<<endl;
CreatebiTree(T);
cout<<"创建树成功!"<<endl;
cout<<"先序遍历:"<<endl;
preorder(T);
cout<<endl<<"中序遍历:"<<endl;
inorder(T);
cout<<endl<<"后序遍历:"<<endl;
posorder(T);
return 0;
}
program 6-6-4 PreinCreateBitree
#include<iostream>
using namespace std;
typedef struct node
{
char data;
struct node *lchild,*rchild;
}BiTNode,*BiTree;
BiTree pre_mid_createBiTree(char *pre,char *mid,int len) //前序中序还原建立二叉树
{
if(len==0)
return NULL;
char ch=pre[0]; //找到先序中的第一个结点
int index=0;
while(mid[index]!=ch)//在中序中找到的根结点的左边为该结点的左子树,右边为右子树
{
index++;
}
BiTree T=new BiTNode;//创建根结点
T->data=ch;
T->lchild=pre_mid_createBiTree(pre+1,mid,index);//建立左子树
T->rchild=pre_mid_createBiTree(pre+index+1,mid+index+1,len-index-1);//建立右子树
return T;
}
BiTree pro_mid_createBiTree(char *last,char *mid,int len)//后序中序还原建立二叉树
{
if(len==0)
return NULL;
char ch=last[len-1]; //取得后序遍历顺序中最后一个结点
int index=0;//在中序序列中找根结点,并用index记录长度
while(mid[index]!=ch)//在中序中找到根结点,左边为该结点的左子树,右边为右子树
index++;
BiTree T=new BiTNode;//创建根结点
T->data=ch;
T->lchild=pro_mid_createBiTree(last,mid,index);//建立左子树
T->rchild=pro_mid_createBiTree(last+index,mid+index+1,len-index-1);//建立右子树
return T;
}
void pre_order(BiTree T)//前序递归遍历二叉树
{
if(T)
{
cout<<T->data;
pre_order(T->lchild);
pre_order(T->rchild);
}
}
void pro_order(BiTree T)//后序递归遍历二叉树
{
if(T)
{
pro_order(T->lchild);
pro_order(T->rchild);
cout<<T->data;
}
}
int main()
{
BiTree T;
int n;
char pre[100],mid[100],last[100];
cout<<"1. 前序中序还原二叉树\n";
cout<<"2. 后序中序还原二叉树\n";
cout<<"0. 退出\n";
int choose=-1;
while(choose!=0)
{
cout<<"请选择:";
cin>>choose;
switch(choose)
{
case 1://前序中序还原二叉树
cout<<"请输入结点的个数:"<<endl;
cin>>n;
cout<<"请输入前序序列:"<<endl;
for(int i=0;i<n;i++)
cin>>pre[i];
cout<<"请输入中序序列:"<<endl;
for(int i=0;i<n;i++)
cin>>mid[i];
T=pre_mid_createBiTree(pre,mid,n);
cout<<endl;
cout<<"二叉树还原成功,输出其后序序列:"<<endl;
pro_order(T);
cout<<endl<<endl;
break;
case 2://后序中序还原二叉树
cout<<"请输入结点的个数:"<<endl;
cin>>n;
cout<<"请输入后序序列:"<<endl;
for(int i=0;i<n;i++)
cin>>last[i];
cout<<"请输入中序序列:"<<endl;
for(int i=0;i<n;i++)
cin>>mid[i];
T=pro_mid_createBiTree(last,mid,n);
cout<<endl;
cout<<"二叉树还原成功,输出其先序序列:"<<endl;
pre_order(T);
cout<<endl<<endl;
break;
}
}
return 0;
}
program 6-6-5 HuffmanTree
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
#define MAXBIT 100
#define MAXVALUE 10000
#define MAXLEAF 30
#define MAXNODE MAXLEAF*2 -1
typedef struct
{
double weight;
int parent;
int lchild;
int rchild;
char value;
}HNodeType; /* 结点结构体 */
typedef struct
{
int bit[MAXBIT];
int start;
}HCodeType; /* 编码结构体 */
HNodeType HuffNode[MAXNODE]; /* 定义一个结点结构体数组 */
HCodeType HuffCode[MAXLEAF];/* 定义一个编码结构体数组*/
/* 构造哈夫曼树 */
void HuffmanTree(HNodeType HuffNode[MAXNODE],int n)
/* i、j:循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,
x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号*/
{
int i,j,x1,x2;
double m1,m2;
/*初始化存放哈夫曼树数组HuffNode[]中的结点 */
for(i=0;i<2*n-1;i++)
{
HuffNode[i].weight=0;//权值
HuffNode[i].parent=-1;
HuffNode[i].lchild=-1;
HuffNode[i].rchild=-1;
}
/* 输入 n 个叶子结点的权值 */
for(i=0;i<n;i++)
{
cout<<"Please input value and weight of leaf node "<<i+1<<endl;
cin>>HuffNode[i].value>>HuffNode[i].weight;
}
/* 构造 Huffman 树 */
for(i=0;i<n-1;i++)
{//执行n-1次合并
m1=m2=MAXVALUE;
/* m1、m2中存放两个无父结点且结点权值最小的两个结点 */
x1=x2=0;
/* 找出所有结点中权值最小、无父结点的两个结点,并合并之为一棵二叉树 */
for(j=0;j<n+i;j++)
{
if(HuffNode[j].weight<m1&&HuffNode[j].parent==-1)
{
m2=m1;
x2=x1;
m1=HuffNode[j].weight;
x1=j;
}
else if(HuffNode[j].weight<m2&&HuffNode[j].parent==-1)
{
m2=HuffNode[j].weight;
x2=j;
}
}
/* 设置找到的两个子结点 x1、x2 的父结点信息 */
HuffNode[x1].parent =n+i;
HuffNode[x2].parent =n+i;
HuffNode[n+i].weight =m1+m2;
HuffNode[n+i].lchild =x1;
HuffNode[n+i].rchild =x2;
cout<<"x1.weight and x2.weight in round "<<i+1<<"\t"<<HuffNode[x1].weight<<"\t"<<HuffNode[x2].weight<<endl; /* 用于测试 */
}
}
/* 哈夫曼树编码 */
void HuffmanCode(HCodeType HuffCode[MAXLEAF],int n){
HCodeType cd; /* 定义一个临时变量来存放求解编码时的信息 */
int i,j,c,p;
for(i=0;i<n;i++)
{
cd.start=n-1;
c=i;
p=HuffNode[c].parent;
while(p!=-1)
{
if(HuffNode[p].lchild==c)
cd.bit[cd.start]=0;
else
cd.bit[cd.start]=1;
cd.start--; /*前移一位 */
c=p;
p=HuffNode[c].parent; /* 设置下一循环条件 */
}
/* 把叶子结点的编码信息从临时编码cd中复制出来,放入编码结构体数组 */
for(j=cd.start+1; j<n; j++)
HuffCode[i].bit[j]=cd.bit[j];
HuffCode[i].start=cd.start;
}
}
int main()
{
int i,j,n;
cout<<"Please input n:"<<endl;
cin>>n;
HuffmanTree(HuffNode,n); //构造哈夫曼树
HuffmanCode(HuffCode,n); // 哈夫曼树编码
//输出已保存好的所有存在编码的哈夫曼编码
for(i=0;i<n;i++)
{
cout<<HuffNode[i].value<<": Huffman code is: ";
for(j=HuffCode[i].start+1;j<n;j++)
cout<<HuffCode[i].bit[j];
cout<<endl;
}
return 0;
}
program 7-2-1 CreateAMGraph
#include<iostream>//邻接矩阵创建无向图
using namespace std;
#define MaxVnum 100 //顶点数最大值
typedef char VexType; //顶点的数据类型,根据需要定义
typedef int EdgeType; //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct{
VexType Vex[MaxVnum];
EdgeType Edge[MaxVnum][MaxVnum];
int vexnum,edgenum; //顶点数,边数
}AMGragh;
int locatevex(AMGragh G,VexType x)
{
for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
if(x==G.Vex[i])
return i;
return -1;//没找到
}
void CreateAMGraph(AMGragh &G)
{
int i,j;
VexType u,v;
cout<<"请输入顶点数:"<<endl;
cin>>G.vexnum;
cout<<"请输入边数:"<<endl;
cin>>G.edgenum;
cout<<"请输入顶点信息:"<<endl;
for(int i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
cin>>G.Vex[i];
for(int i=0;i<G.vexnum;i++)//初始化邻接矩阵所有值为0,如果是网,则初始化邻接矩阵为无穷大
for(int j=0;j<G.vexnum;j++)
G.Edge[i][j]=0;
cout<<"请输入每条边依附的两个顶点:"<<endl;
while(G.edgenum--)
{
cin>>u>>v;
i=locatevex(G,u);//查找顶点u的存储下标
j=locatevex(G,v);//查找顶点v的存储下标
if(i!=-1&&j!=-1)
G.Edge[i][j]=G.Edge[j][i]=1; //邻接矩阵储置1
else
{
cout<<"输入顶点信息错!请重新输入!"<<endl;
G.edgenum++;//本次输入不算
}
}
}
void print(AMGragh G)//输出邻接矩阵
{
cout<<"图的邻接矩阵为:"<<endl;
for(int i=0;i<G.vexnum;i++)
{
for(int j=0;j<G.vexnum;j++)
cout<<G.Edge[i][j]<<"\t";
cout<<endl;
}
}
int main()
{
AMGragh G;
CreateAMGraph(G);
print(G);
return 0;
}
/*
4 5
a b c d
a b
a d
b c
b d
c d
*/
program 7-2-2 CreateALGraph
#include<iostream>//创建有向图的邻接表
using namespace std;
const int MaxVnum=100;//顶点数最大值
typedef char VexType;//顶点的数据类型为字符型
typedef struct AdjNode{ //定义邻接点类型
int v; //邻接点下标
struct AdjNode *next; //指向下一个邻接点
}AdjNode;
typedef struct VexNode{ //定义顶点类型
VexType data; // VexType为顶点的数据类型,根据需要定义
AdjNode *first; //指向第一个邻接点
}VexNode;
typedef struct{//定义邻接表类型
VexNode Vex[MaxVnum];
int vexnum,edgenum; //顶点数,边数
}ALGragh;
int locatevex(ALGragh G,VexType x)
{
for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
if(x==G.Vex[i].data)
return i;
return -1;//没找到
}
void insertedge(ALGragh &G,int i,int j)//插入一条边
{
AdjNode *s;
s=new AdjNode;
s->v=j;
s->next=G.Vex[i].first;
G.Vex[i].first=s;
}
void printg(ALGragh G)//输出邻接表
{
cout<<"----------邻接表如下:----------"<<endl;
for(int i=0;i<G.vexnum;i++)
{
AdjNode *t=G.Vex[i].first;
cout<<cout<<G.Vex[i].data<<": ";
while(t!=NULL)
{
cout<<"["<<t->v<<"] ";
t=t->next;
}
cout<<endl;
}
}
void CreateALGraph(ALGragh &G)//创建有向图邻接表
{
int i,j;
VexType u,v;
cout<<"请输入顶点数和边数:"<<endl;
cin>>G.vexnum>>G.edgenum;
cout<<"请输入顶点信息:"<<endl;
for(i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
cin>>G.Vex[i].data;
for(i=0;i<G.vexnum;i++)
G.Vex[i].first=NULL;
cout<<"请依次输入每条边的两个顶点u,v"<<endl;
while(G.edgenum--)
{
cin>>u>>v;
i=locatevex(G,u);//查找顶点u的存储下标
j=locatevex(G,v);//查找顶点v的存储下标
if(i!=-1&&j!=-1)
insertedge(G,i,j);
else
{
cout<<"输入顶点信息错!请重新输入!"<<endl;
G.edgenum++;//本次输入不算
}
}
}
int main()
{
ALGragh G;
CreateALGraph(G);//创建有向图邻接表
printg(G);//输出邻接表
return 0;
}
/*
5 7
a b c d e
a b
a c
a e
b c
c d
c e
d e
*/
program 7-3-1 BFS_AL
#include<iostream>
#include<queue>//引入队列头文件
using namespace std;
const int MaxVnum=100;//顶点数最大值
bool visited[MaxVnum];//访问标志数组,其初值为"false"
typedef char VexType;//顶点的数据类型为字符型
typedef struct AdjNode{ //定义邻接点类型
int v; //邻接点下标
struct AdjNode *next; //指向下一个邻接点
}AdjNode;
typedef struct VexNode{ //定义顶点类型
VexType data; // VexType为顶点的数据类型,根据需要定义
AdjNode *first; //指向第一个邻接点
}VexNode;
typedef struct{//定义邻接表类型
VexNode Vex[MaxVnum];
int vexnum,edgenum; //顶点数,边数
}ALGragh;
int locatevex(ALGragh G,VexType x)
{
for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
if(x==G.Vex[i].data)
return i;
return -1;//没找到
}
void insertedge(ALGragh &G,int i,int j)//插入一条边
{
AdjNode *s;
s=new AdjNode;
s->v=j;
s->next=G.Vex[i].first;
G.Vex[i].first=s;
}
void printg(ALGragh G)//输出邻接表
{
cout<<"----------邻接表如下:----------"<<endl;
for(int i=0;i<G.vexnum;i++)
{
AdjNode *t=G.Vex[i].first;
cout<<G.Vex[i].data<<": ";
while(t!=NULL)
{
cout<<"["<<t->v<<"] ";
t=t->next;
}
cout<<endl;
}
}
void CreateALGraph(ALGragh &G)//创建有向图邻接表
{
int i,j;
VexType u,v;
cout<<"请输入顶点数和边数:"<<endl;
cin>>G.vexnum>>G.edgenum;
cout<<"请输入顶点信息:"<<endl;
for(i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
cin>>G.Vex[i].data;
for(i=0;i<G.vexnum;i++)
G.Vex[i].first=NULL;
cout<<"请依次输入每条边的两个顶点u,v"<<endl;
while(G.edgenum--)
{
cin>>u>>v;
i=locatevex(G,u);//查找顶点u的存储下标
j=locatevex(G,v);//查找顶点v的存储下标
if(i!=-1&&j!=-1)
insertedge(G,i,j);
else
{
cout<<"输入顶点信息错!请重新输入!"<<endl;
G.edgenum++;//本次输入不算
}
}
}
void BFS_AL(ALGragh G,int v)//基于邻接表的广度优先遍历
{
int u,w;
AdjNode *p;
queue<int>Q; //创建一个普通队列(先进先出),里面存放int类型
cout<<G.Vex[v].data<<"\t";
visited[v]=true;
Q.push(v); //源点v入队
while(!Q.empty()) //如果队列不空
{
u=Q.front();//取出队头元素赋值给u
Q.pop(); //队头元素出队
p=G.Vex[u].first;
while(p)//依次检查u的所有邻接点
{
w=p->v;//w为u的邻接点
if(!visited[w])//w未被访问
{
cout<<G.Vex[w].data<<"\t";
visited[w]=true;
Q.push(w);
}
p=p->next;
}
}
}
void BFS_AL(ALGragh G)//非连通图,基于邻接表的广度优先遍历
{
for(int i=0;i<G.vexnum;i++)//非连通图需要查漏点,检查未被访问的顶点
if(!visited[i])//i未被访问,以i为起点再次广度优先遍历
BFS_AL(G,i);
}
int main()
{
ALGragh G;
int v;
VexType c;
CreateALGraph(G);//创建有向图邻接表
printg(G);//输出邻接表
cout<<"请输入遍历连通图的起始点:";
cin>>c;
v=locatevex(G,c);//查找顶点u的存储下标
if(v!=-1)
{
cout<<"广度优先搜索遍历连通图结果:"<<endl;
BFS_AL(G,v);
}
else
cout<<"输入顶点信息错!请重新输入!"<<endl;
return 0;
}
/*测试数据
6 9
1 2 3 4 5 6
1 3
1 2
2 4
3 5
3 2
4 6
4 3
5 6
5 4
1
*/
program 7-3-1 BFS_AM
#include<iostream>
#include<queue>//引入队列头文件
using namespace std;
#define MaxVnum 100 //顶点数最大值
bool visited[MaxVnum]; //访问标志数组,其初值为"false"
typedef char VexType; //顶点的数据类型,根据需要定义
typedef int EdgeType; //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct{
VexType Vex[MaxVnum];
EdgeType Edge[MaxVnum][MaxVnum];
int vexnum,edgenum; //顶点数,边数
}AMGragh;
int locatevex(AMGragh G,VexType x)
{
for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
if(x==G.Vex[i])
return i;
return -1;//没找到
}
void CreateAMGraph(AMGragh &G)//创建有向图的邻接矩阵
{
int i,j;
VexType u,v;
cout<<"请输入顶点数:"<<endl;
cin>>G.vexnum;
cout<<"请输入边数:"<<endl;
cin>>G.edgenum;
cout<<"请输入顶点信息:"<<endl;
for(int i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
cin>>G.Vex[i];
for(int i=0;i<G.vexnum;i++)//初始化邻接矩阵所有值为0,如果是网,则初始化邻接矩阵为无穷大
for(int j=0;j<G.vexnum;j++)
G.Edge[i][j]=0;
cout<<"请输入每条边依附的两个顶点:"<<endl;
while(G.edgenum--)
{
cin>>u>>v;
i=locatevex(G,u);//查找顶点u的存储下标
j=locatevex(G,v);//查找顶点v的存储下标
if(i!=-1&&j!=-1)
G.Edge[i][j]=1; //邻接矩阵储置1,若无向图G.Edge[i][j]=G.Edge[j][i]=1
else
{
cout<<"输入顶点信息错!请重新输入!"<<endl;
G.edgenum++;//本次输入不算
}
}
}
void print(AMGragh G)//输出邻接矩阵
{
cout<<"图的邻接矩阵为:"<<endl;
for(int i=0;i<G.vexnum;i++)
{
for(int j=0;j<G.vexnum;j++)
cout<<G.Edge[i][j]<<"\t";
cout<<endl;
}
}
void BFS_AM(AMGragh G,int v)//基于邻接矩阵的广度优先遍历
{
int u,w;
queue<int>Q; //创建一个普通队列(先进先出),里面存放int类型
cout<<G.Vex[v]<<"\t";
visited[v]=true;
Q.push(v); //源点v入队
while(!Q.empty()) //如果队列不空
{
u=Q.front();//取出队头元素赋值给u
Q.pop(); //队头元素出队
for(w=0;w<G.vexnum;w++)//依次检查u的所有邻接点
{
if(G.Edge[u][w]&&!visited[w])//u、w邻接而且w未被访问
{
cout<<G.Vex[w]<<"\t";
visited[w]=true;
Q.push(w);
}
}
}
}
int main()
{
int v;
VexType c;
AMGragh G;
CreateAMGraph(G);
print(G);
cout << "请输入遍历连通图的起始点:";
cin>>c;
v=locatevex(G,c);//查找顶点u的存储下标
if(v!=-1)
{
cout << "广度优先搜索遍历连通图结果:" <<endl;
BFS_AM(G,v);
}
else
cout << "输入顶点信息错!请重新输入!"<<endl;
return 0;
}
/*测试数据
6 9
1 2 3 4 5 6
1 3
1 2
2 4
3 5
3 2
4 6
4 3
5 6
5 4
1
*/
program 7-3-2 DFS_AL
#include<iostream>
using namespace std;
const int MaxVnum=100;//顶点数最大值
bool visited[MaxVnum]; //访问标志数组,其初值为"false"
typedef char VexType;//顶点的数据类型为字符型
typedef struct AdjNode{ //定义邻接点类型
int v; //邻接点下标
struct AdjNode *next; //指向下一个邻接点
}AdjNode;
typedef struct VexNode{ //定义顶点类型
VexType data; // VexType为顶点的数据类型,根据需要定义
AdjNode *first; //指向第一个邻接点
}VexNode;
typedef struct{//定义邻接表类型
VexNode Vex[MaxVnum];
int vexnum,edgenum; //顶点数,边数
}ALGragh;
int locatevex(ALGragh G,VexType x)
{
for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
if(x==G.Vex[i].data)
return i;
return -1;//没找到
}
void insertedge(ALGragh &G,int i,int j)//插入一条边
{
AdjNode *s;
s=new AdjNode;
s->v=j;
s->next=G.Vex[i].first;
G.Vex[i].first=s;
}
void printg(ALGragh G)//输出邻接表
{
cout<<"----------邻接表如下:----------"<<endl;
for(int i=0;i<G.vexnum;i++)
{
AdjNode *t=G.Vex[i].first;
cout<<G.Vex[i].data<<": ";
while(t!=NULL)
{
cout<<"["<<t->v<<"] ";
t=t->next;
}
cout<<endl;
}
}
void CreateALGraph(ALGragh &G)//创建无向图邻接表
{
int i,j;
VexType u,v;
cout<<"请输入顶点数和边数:"<<endl;
cin>>G.vexnum>>G.edgenum;
cout<<"请输入顶点信息:"<<endl;
for(i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
cin>>G.Vex[i].data;
for(i=0;i<G.vexnum;i++)
G.Vex[i].first=NULL;
cout<<"请依次输入每条边的两个顶点u,v"<<endl;
while(G.edgenum--)
{
cin>>u>>v;
i=locatevex(G,u);//查找顶点u的存储下标
j=locatevex(G,v);//查找顶点v的存储下标
if(i!=-1&&j!=-1)
{
insertedge(G,i,j);
insertedge(G,j,i);//无向图多插入一条边
}
else
{
cout<<"输入顶点信息错!请重新输入!"<<endl;
G.edgenum++;//本次输入不算
}
}
}
void DFS_AL(ALGragh G,int v)//基于邻接表的深度优先遍历
{
int w;
AdjNode *p;
cout<<G.Vex[v].data<<"\t";
visited[v]=true;
p=G.Vex[v].first;
while(p)//依次检查v的所有邻接点
{
w=p->v;//w为v的邻接点
if(!visited[w])//w未被访问
DFS_AL(G,w);//从w出发,递归深度优先遍历
p=p->next;
}
}
void DFS_AL(ALGragh G)//非连通图,基于邻接表的深度优先遍历
{
for(int i=0;i<G.vexnum;i++)//非连通图需要查漏点,检查未被访问的顶点
if(!visited[i])//i未被访问,以i为起点再次广度优先遍历
DFS_AL(G,i);
}
int main()
{
ALGragh G;
int v;
VexType c;
CreateALGraph(G);//创建有向图邻接表
printg(G);//输出邻接表
cout<<"请输入遍历连通图的起始点:";
cin>>c;
v=locatevex(G,c);//查找顶点u的存储下标
if(v!=-1)
{
cout<<"深度优先搜索遍历连通图结果:"<<endl;
DFS_AL(G,v);
}
else
cout<<"输入顶点信息错!请重新输入!"<<endl;
return 0;
}
/*测试数据
8 9
1 2 3 4 5 6 7 8
1 3
1 2
2 6
2 5
2 4
3 8
3 7
4 5
7 8
1
*/
program 7-3-2 DFS_AM
#include<iostream>
using namespace std;
#define MaxVnum 100 //顶点数最大值
bool visited[MaxVnum]; //访问标志数组,其初值为"false"
typedef char VexType; //顶点的数据类型,根据需要定义
typedef int EdgeType; //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct{
VexType Vex[MaxVnum];
EdgeType Edge[MaxVnum][MaxVnum];
int vexnum,edgenum; //顶点数,边数
}AMGragh;
int locatevex(AMGragh G,VexType x)
{
for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
if(x==G.Vex[i])
return i;
return -1;//没找到
}
void CreateAMGraph(AMGragh &G)//创建无向图的邻接矩阵
{
int i,j;
VexType u,v;
cout<<"请输入顶点数:"<<endl;
cin>>G.vexnum;
cout<<"请输入边数:"<<endl;
cin>>G.edgenum;
cout<<"请输入顶点信息:"<<endl;
for(int i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
cin>>G.Vex[i];
for(int i=0;i<G.vexnum;i++)//初始化邻接矩阵所有值为0,如果是网,则初始化邻接矩阵为无穷大
for(int j=0;j<G.vexnum;j++)
G.Edge[i][j]=0;
cout<<"请输入每条边依附的两个顶点:"<<endl;
while(G.edgenum--)
{
cin>>u>>v;
i=locatevex(G,u);//查找顶点u的存储下标
j=locatevex(G,v);//查找顶点v的存储下标
if(i!=-1&&j!=-1)
G.Edge[i][j]=G.Edge[j][i]=1; //邻接矩阵储置1,若有向图G.Edge[i][j]=1
else
{
cout<<"输入顶点信息错!请重新输入!"<<endl;
G.edgenum++;//本次输入不算
}
}
}
void print(AMGragh G)//输出邻接矩阵
{
cout<<"图的邻接矩阵为:"<<endl;
for(int i=0;i<G.vexnum;i++)
{
for(int j=0;j<G.vexnum;j++)
cout<<G.Edge[i][j]<<"\t";
cout<<endl;
}
}
void DFS_AM(AMGragh G,int v)//基于邻接矩阵的深度优先遍历
{
int w;
cout<<G.Vex[v]<<"\t";
visited[v]=true;
for(w=0;w<G.vexnum;w++)//依次检查v的所有邻接点
if(G.Edge[v][w]&&!visited[w])//v、w邻接而且w未被访问
DFS_AM(G,w);//从w顶点开始递归深度优先遍历
}
int main()
{
int v;
VexType c;
AMGragh G;
CreateAMGraph(G);
print(G);
cout<<"请输入遍历连通图的起始点:";
cin>>c;
v=locatevex(G,c);//查找顶点u的存储下标
if(v!=-1)
{
cout<<"深度优先搜索遍历连通图结果:"<<endl;
DFS_AM(G,v);
}
else
cout<<"输入顶点信息错!请重新输入!"<<endl;
return 0;
}
/*测试数据
8 9
1 2 3 4 5 6 7 8
1 3
1 2
2 6
2 5
2 4
3 8
3 7
4 5
7 8
1
*/
program 7-4-1 Dijkstra
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
const int MaxVnum=100; // 城市的个数可修改
const int INF=1e7; // 无穷大10000000
int dist[MaxVnum],p[MaxVnum];//最短距离和前驱数组
bool flag[MaxVnum]; //如果s[i]等于true,说明顶点i已经加入到集合S;否则顶点i属于集合V-S
typedef string VexType; //顶点的数据类型,根据需要定义
typedef int EdgeType; //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct{
VexType Vex[MaxVnum];
EdgeType Edge[MaxVnum][MaxVnum];
int vexnum,edgenum; //顶点数,边数
}AMGragh;
int locatevex(AMGragh G,VexType x)
{
for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
if(x==G.Vex[i])
return i;
return -1;//没找到
}
void CreateAMGraph(AMGragh &G)
{
int i,j,w;
VexType u,v;
cout<<"请输入顶点数:"<<endl;
cin>>G.vexnum;
cout<<"请输入边数:"<<endl;
cin>>G.edgenum;
cout<<"请输入顶点信息:"<<endl;
for(int i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
cin>>G.Vex[i];
for(int i=0;i<G.vexnum;i++)//初始化邻接矩阵为无穷大
for(int j=0;j<G.vexnum;j++)
G.Edge[i][j]=INF;
cout<<"请输入每条边依附的两个顶点及权值:"<<endl;
while(G.edgenum--)
{
cin>>u>>v>>w;
i=locatevex(G,u);//查找顶点u的存储下标
j=locatevex(G,v);//查找顶点v的存储下标
if(i!=-1&&j!=-1)
G.Edge[i][j]=w; //有向图邻接矩阵
else
{
cout<<"输入顶点信息错!请重新输入!"<<endl;
G.edgenum++;//本次输入不算
}
}
}
void Dijkstra(AMGragh G,int u)
{
for(int i=0;i<G.vexnum;i++)
{
dist[i]=G.Edge[u][i]; //初始化源点u到其他各个顶点的最短路径长度
flag[i]=false;
if(dist[i]==INF)
p[i]=-1; //源点u到该顶点的路径长度为无穷大,说明顶点i与源点u不相邻
else
p[i]=u; //说明顶点i与源点u相邻,设置顶点i的前驱p[i]=u
}
dist[u]=0;
flag[u]=true; //初始时,集合S中只有一个元素:源点u
for(int i=0;i<G.vexnum;i++)
{
int temp=INF,t=u;
for(int j=0;j<G.vexnum;j++) //在集合V-S中寻找距离源点u最近的顶点t
if(!flag[j]&&dist[j]<temp)
{
t=j;
temp=dist[j];
}
if(t==u) return ; //找不到t,跳出循环
flag[t]=true; //否则,将t加入集合
for(int j=0;j<G.vexnum;j++)//更新与t相邻接的顶点到源点u的距离
if(!flag[j]&&G.Edge[t][j]<INF)
if(dist[j]>(dist[t]+G.Edge[t][j]))
{
dist[j]=dist[t]+G.Edge[t][j];
p[j]=t;
}
}
}
void findpath(AMGragh G,VexType u)
{
int x;
stack<int>S;
cout<<"源点为:"<<u<<endl;
for(int i=0;i<G.vexnum;i++)
{
x=p[i];
if(x==-1&&u!=G.Vex[i])
{
cout<<"源点到其它各顶点最短路径为:"<<u<<"--"<<G.Vex[i]<<" sorry,无路可达"<<endl;
continue;
}
while(x!=-1)
{
S.push(x);
x=p[x];
}
cout<<"源点到其它各顶点最短路径为:";
while(!S.empty())
{
cout<<G.Vex[S.top()]<<"--";
S.pop();
}
cout<<G.Vex[i]<<" 最短距离为:"<<dist[i]<<endl;
}
}
int main()
{
AMGragh G;
int st;
VexType u;
CreateAMGraph(G);
cout<<"请输入源点的信息:"<<endl;
cin>>u;
st=locatevex(G,u);//查找源点u的存储下标
Dijkstra(G,st);
cout<<"小明所在的位置:"<<u<<endl;
for(int i=0;i<G.vexnum;i++)
{
cout<<"小明:"<<u<<" - "<<"要去的位置:"<<G.Vex[i];
if(dist[i]==INF)
cout<<"sorry,无路可达"<<endl;
else
cout<<"最短距离为:"<<dist[i]<<endl;
}
findpath(G,u);
return 0;
}
/*
5 8
1 2 3 4 5
1 2 2
1 3 5
2 3 2
2 4 6
3 4 7
3 5 1
4 3 2
4 5 4
1
*/
program 7-4-2 Floyd
#include<iostream>
#include<cstring>
#include<windows.h>
using namespace std;
#define MaxVnum 100 //顶点数最大值
const int INF=1e7; // 无穷大10000000
typedef string VexType; //顶点的数据类型,根据需要定义
typedef int EdgeType; //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct{
VexType Vex[MaxVnum];
EdgeType Edge[MaxVnum][MaxVnum];
int vexnum,edgenum; //顶点数,边数
}AMGragh;
int dist[MaxVnum][MaxVnum],p[MaxVnum][MaxVnum];
int locatevex(AMGragh G,VexType x)
{
for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
if(x==G.Vex[i])
return i;
return -1;//没找到
}
void CreateAMGraph(AMGragh &G)//创建无向图的邻接矩阵
{
int i,j,w;
VexType u,v;
cout<<"请输入顶点数:"<<endl;
cin>>G.vexnum;
cout<<"请输入边数:"<<endl;
cin>>G.edgenum;
cout<<"请输入顶点信息:"<<endl;
for(int i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
cin>>G.Vex[i];
for(int i=0;i<G.vexnum;i++)//初始化邻接矩阵所有值为0,若是网,则初始化为无穷大
for(int j=0;j<G.vexnum;j++)
if(i!=j)
G.Edge[i][j]=INF;
else
G.Edge[i][j]=0; //注意i==j时,设置为0
cout<<"请输入每条边依附的两个顶点及权值:"<<endl;
while(G.edgenum--)
{
cin>>u>>v>>w;
i=locatevex(G,u);//查找顶点u的存储下标
j=locatevex(G,v);//查找顶点v的存储下标
if(i!=-1&&j!=-1)
G.Edge[i][j]=w; //有向图邻接矩阵存储权值
}
}
void Floyd(AMGragh G) //用Floyd算法求有向网G中各对顶点i和j之间的最短路径
{
int i,j,k;
for(i=0;i<G.vexnum;i++) //各对结点之间初始已知路径及距离
for(j=0;j<G.vexnum;j++)
{
dist[i][j]=G.Edge[i][j];
if(dist[i][j]<INF && i!=j)
p[i][j]=i; //如果i和j之间有弧,则将j的前驱置为i
else p[i][j]=-1; //如果i和j之间无弧,则将j的前驱置为-1
}
for(k=0;k<G.vexnum; k++)
for(i=0;i<G.vexnum; i++)
for(j=0;j<G.vexnum; j++)
if(dist[i][k]+dist[k][j]<dist[i][j])//从i经k到j的一条路径更短
{
dist[i][j]=dist[i][k]+dist[k][j]; //更新dist[i][j]
p[i][j]=p[k][j]; //更改j的前驱为k
}
}
void print(AMGragh G)
{
int i,j;
for(i=0;i<G.vexnum;i++)//输出最短距离数组
{
for(j=0;j<G.vexnum;j++)
cout<<dist[i][j]<<"\t";
cout<<endl;
}
cout<<endl;
for(i=0;i<G.vexnum;i++)//输出前驱数组
{
for(j=0;j<G.vexnum;j++)
cout<<p[i][j]<<"\t";
cout<<endl;
}
}
void DisplayPath(AMGragh G,int s,int t )//显示最短路径
{
if(p[s][t]!=-1)
{
DisplayPath(G,s,p[s][t]);
cout<<G.Vex[p[s][t]]<<"-->";
}
}
int main()
{
VexType start,destination;
int u,v;
system("color 0d");
AMGragh G;
CreateAMGraph(G);
Floyd(G);
print(G);
cout<<"请依次输入路径的起点与终点的名称:";
cin>>start>>destination;
u=locatevex(G,start);
v=locatevex(G,destination);
DisplayPath(G,u,v);
cout<<G.Vex[v]<<endl;
cout<<"最短路径的长度为:"<<dist[u][v]<<endl;
cout<<endl;
return 0;
}
/*
4 8
0 1 2 3
0 1 1
0 3 4
1 2 9
1 3 2
2 0 3
2 1 5
2 3 8
3 2 6
0 2
*/
program 7-4-3 Prim
#include<iostream>
using namespace std;
const int INF=0x3fffffff;
const int N=100;
bool s[N];
int c[N][N],closest[N],lowcost[N];
void Prim(int n, int u0, int c[N][N])
{ //顶点个数n、开始顶点u0、带权邻接矩阵C[n][n]
//如果s[i]=true,说明顶点i已加入最小生成树
//的顶点集合U;否则顶点i属于集合V-U
//将最后的相关的最小权值传递到数组lowcost
s[u0]=true; //初始时,集合中U只有一个元素,即顶点u0
int i,j;
for(i=1;i<=n;i++)
{
if(i!=u0)
{
lowcost[i]=c[u0][i];
closest[i]=u0;
s[i]=false;
}
else
lowcost[i]=0;
}
for(i=1;i<=n;i++) //在集合中V-u中寻找距离集合U最近的顶点t
{
int temp=INF;
int t=u0;
for(j=1;j<=n;j++)
{
if((!s[j])&&(lowcost[j]<temp))
{
t=j;
temp=lowcost[j];
}
}
if(t==u0)
break; //找不到t,跳出循环
s[t]=true; //否则,讲t加入集合U
for(j=1;j<=n;j++) //更新lowcost和closest
{
if((!s[j])&&(c[t][j]<lowcost[j]))
{
lowcost[j]=c[t][j];
closest[j]=t;
}
}
}
}
int main()
{
int n,m,u,v,w;
int u0;
cout<<"输入结点数n和边数m:"<<endl;
cin>>n>>m;
int sumcost=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
c[i][j]=INF;
cout<<"输入结点数u,v和边值w:"<<endl;
for(int i=1;i<=m;i++)
{
cin>>u>>v>>w;
c[u][v]=c[v][u]=w;
}
cout<<"输入任一结点u0:"<<endl;
cin>>u0 ;
//计算最后的lowcos的总和,即为最后要求的最小的费用之和
Prim(n,u0,c);
cout<<"数组lowcost的内容为"<<endl;
for(int i=1;i<=n;i++)
cout<<lowcost[i]<<" ";
cout<<endl;
for(int i=1;i<=n;i++)
sumcost+=lowcost[i];
cout<<"最小的花费是:"<<sumcost<<endl;
return 0;
}
/*测试数据
7 12
1 2 23
1 6 28
1 7 36
2 3 20
2 7 1
3 4 15
3 7 4
4 5 3
4 7 9
5 6 17
5 7 16
6 7 25
输出结果:
数组lowcost:
0 23 4 9 3 17 1
最小的花费:57
*/
program 7-4-4 Kruskal
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100;
int nodeset[N];
int n, m;
struct Edge{
int u;
int v;
int w;
}e[N*N];
bool comp(Edge x, Edge y){
return x.w<y.w;
}
void Init(int n)
{
for(int i=1;i<=n;i++)
nodeset[i]=i;
}
int Merge(int a, int b)
{
int p=nodeset[a];
int q=nodeset[b];
if(p==q) return 0;
for(int i=1;i<=n;i++)//检查所有结点,把集合号是q的改为p
{
if(nodeset[i]==q)
nodeset[i]=p;//a的集合号赋值给b集合号
}
return 1;
}
int Kruskal(int n)
{
int ans=0;
for(int i=0;i<m;i++)
if(Merge(e[i].u,e[i].v))
{
ans+=e[i].w;
n--;
if(n==1)
return ans;
}
return 0;
}
int main()
{
cout<<"输入结点数n和边数m:"<<endl;
cin>>n>>m;
Init(n);
cout<<"输入结点数u,v和边值w:"<<endl;
for(int i=1;i<=m;i++)
cin>>e[i].u>>e[i].v>>e[i].w;
sort(e,e+m,comp);
int ans=Kruskal(n);
cout<<"最小的花费是:"<<ans<<endl;
return 0;
}
/*测试数据
7 12
1 2 23
1 6 28
1 7 36
2 3 20
2 7 1
3 4 15
3 7 4
4 5 3
4 7 9
5 6 17
5 7 16
6 7 25
*/
program 7-4-5 TopoSort
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
const int MaxVnum=100;//顶点数最大值
int indegree[MaxVnum];//入度数组
typedef string VexType;//顶点的数据类型为字符型
typedef struct AdjNode{ //定义邻接点类型
int v; //邻接点下标
struct AdjNode *next; //指向下一个邻接点
}AdjNode;
typedef struct VexNode{ //定义顶点类型
VexType data; // VexType为顶点的数据类型,根据需要定义
AdjNode *first; //指向第一个邻接点
}VexNode;
typedef struct{//包含邻接表和逆邻接表
VexNode Vex[MaxVnum]; //定义邻接表
VexNode converse_Vex[MaxVnum]; //定义逆邻接表
int vexnum,edgenum; //顶点数,边数
}ALGragh;
int locatevex(ALGragh G,VexType x)
{
for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
if(x==G.Vex[i].data)
return i;
return -1;//没找到
}
void insertedge(ALGragh &G,int i,int j)//插入一条边
{
AdjNode *s1,*s2;
s1=new AdjNode;//创建邻接表结点
s1->v=j;
s1->next=G.Vex[i].first;
G.Vex[i].first=s1;
s2=new AdjNode;//创建逆邻接表结点
s2->v=i;
s2->next=G.converse_Vex[j].first;
G.converse_Vex[j].first=s2;
}
void printg(ALGragh G)//输出邻接表
{
cout<<"----------邻接表如下:----------"<<endl;
for(int i=0;i<G.vexnum;i++)
{
AdjNode *t=G.Vex[i].first;
cout<<G.Vex[i].data<<": ";
while(t!=NULL)
{
cout<<"["<<t->v<<"] ";
t=t->next;
}
cout<<endl;
}
cout<<"----------逆邻接表如下:----------"<<endl;
for(int i=0;i<G.vexnum;i++)
{
AdjNode *t=G.converse_Vex[i].first;
cout<<G.converse_Vex[i].data<<": ";
while(t!=NULL)
{
cout<<"["<<t->v<<"] ";
t=t->next;
}
cout<<endl;
}
}
void CreateALGraph(ALGragh &G)//创建有向图的邻接表和逆邻接表
{
int i,j;
VexType u,v;
cout<<"请输入顶点数和边数:"<<endl;
cin>>G.vexnum>>G.edgenum;
cout<<"请输入顶点信息:"<<endl;
for(i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
{
cin>>G.Vex[i].data;
G.converse_Vex[i].data=G.Vex[i].data;
G.Vex[i].first=NULL;
G.converse_Vex[i].first=NULL;
}
cout<<"请依次输入每条边的两个顶点u,v"<<endl;
while(G.edgenum--)
{
cin>>u>>v;
i=locatevex(G,u);//查找顶点u的存储下标
j=locatevex(G,v);//查找顶点v的存储下标
if(i!=-1&&j!=-1)
insertedge(G,i,j);
else
{
cout<<"输入顶点信息错!请重新输入!"<<endl;
G.edgenum++;//本次输入不算
}
}
}
void FindInDegree(ALGragh G)//求出各顶点的入度存入数组indegree中
{
int i,count;
for(i=0;i<G.vexnum;i++)
{
count=0;
AdjNode *p=G.converse_Vex[i].first;
if(p)
{
while(p)
{
p=p->next;
count++;
}
}
indegree[i]=count;
}
cout<<"入度数组为:"<<endl;
for(int i=0;i<G.vexnum;i++)//输出入度数组
cout<<indegree[i]<<"\t";
cout<<endl;
}
bool TopologicalSort(ALGragh G, int topo[])//拓扑排序
{
//有向图G采用邻接表存储结构
//若G无回路,则生成G的一个拓扑序列topo[]并返回true,否则false
int i,m;
stack<int>S; //初始化一个栈S,需要引入头文件#include<stack>
FindInDegree(G); //求出各顶点的入度存入数组indegree[]中
for(i=0;i<G.vexnum;i++)
if(!indegree[i])//入度为0者进栈
S.push(i);
m=0; //对输出顶点计数,初始为0
while(!S.empty())//栈S非空
{
i=S.top(); //取栈顶顶点i
S.pop(); //栈顶顶点i出栈
topo[m]=i; //将i保存在拓扑序列数组topo中
m++; //对输出顶点计数
AdjNode *p=G.Vex[i].first; //p指向i的第一个邻接点
while(p) //i的所有邻接点入度减1
{
int k=p->v; //k为i的邻接点
--indegree[k]; //i的每个邻接点的入度减1
if(indegree[k]==0) //若入度减为0,则入栈
S.push(k);
p=p->next; //p指向顶点i下一个邻接结点
}
}
if(m<G.vexnum)//该有向图有回路
return false;
else
return true;
}
int main()
{
ALGragh G;
int *topo=new int[G.vexnum];
CreateALGraph(G);//创建有向图的邻接表和逆邻接表
printg(G);//输出邻接表和逆邻接表
if(TopologicalSort(G,topo))
{
cout<<"拓扑序列为:"<<endl;
for(int i=0;i<G.vexnum;i++)//输出拓扑序列
cout<<topo[i]<<"\t";
}
else
cout<<"该图有环,无拓扑序列!"<<endl;
return 0;
}
program 7-4-6 CriticalPath
#include<iostream>
#include<cstring>
#include<stack>
using namespace std;
const int MaxVnum=100;//顶点数最大值
int indegree[MaxVnum];//入度数组
int ve[MaxVnum]; //事件vi的最早发生时间
int vl[MaxVnum]; //事件vi的最迟发生时间
typedef string VexType;//顶点的数据类型为字符型
typedef struct AdjNode{ //定义邻接点类型
int v; //邻接点下标
int weight; //权值
struct AdjNode *next; //指向下一个邻接点指针
}AdjNode;
typedef struct VexNode{ //定义顶点类型
VexType data; //VexType为顶点的数据类型,根据需要定义
AdjNode *first; //指向第一个邻接点指针
}VexNode;
typedef struct{ //包含邻接表和逆邻接表
VexNode Vex[MaxVnum]; //定义邻接表
VexNode converse_Vex[MaxVnum]; //定义逆邻接表
int vexnum,edgenum; //顶点数,边数
}ALGragh;
int locatevex(ALGragh G,VexType x)
{
for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标
if(x==G.Vex[i].data)
return i;
return -1;//没找到
}
void insertedge(ALGragh &G,int i,int j,int w)//插入一条边
{
AdjNode *s1,*s2;
//创建邻接表结点
s1=new AdjNode;
s1->v=j;
s1->weight=w;
s1->next=G.Vex[i].first;
G.Vex[i].first=s1;
//创建逆邻接表结点
s2=new AdjNode;
s2->v=i;
s2->weight=w;
s2->next=G.converse_Vex[j].first;
G.converse_Vex[j].first=s2;
}
void printg(ALGragh G)//输出邻接表
{
cout<<"----------邻接表如下:----------"<<endl;
for(int i=0;i<G.vexnum;i++)
{
AdjNode *t=G.Vex[i].first;
cout<<G.Vex[i].data<<": ";
while(t!=NULL)
{
cout<<"["<<t->v<<" "<<t->weight<<"] ";
t=t->next;
}
cout<<endl;
}
cout<<"----------逆邻接表如下:----------"<<endl;
for(int i=0;i<G.vexnum;i++)
{
AdjNode *t=G.converse_Vex[i].first;
cout<<G.converse_Vex[i].data<<": ";
while(t!=NULL)
{
cout<<"["<<t->v<<" "<<t->weight<<"] ";
t=t->next;
}
cout<<endl;
}
}
void CreateALGraph(ALGragh &G)//创建有向图的邻接表和逆邻接表
{
int i,j,w;
VexType u,v;
cout<<"请输入顶点数和边数:"<<endl;
cin>>G.vexnum>>G.edgenum;
cout<<"请输入顶点信息:"<<endl;
for(i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组
{
cin>>G.Vex[i].data;
G.converse_Vex[i].data=G.Vex[i].data;
G.Vex[i].first=NULL;
G.converse_Vex[i].first=NULL;
}
cout<<"请依次输入每条边的两个顶点及权值u,v,w"<<endl;
while(G.edgenum--)
{
cin>>u>>v>>w;
i=locatevex(G,u);//查找顶点u的存储下标
j=locatevex(G,v);//查找顶点v的存储下标
if(i!=-1&&j!=-1)
insertedge(G,i,j,w);
else
{
cout<<"输入顶点信息错!请重新输入!"<<endl;
G.edgenum++;//本次输入不算
}
}
}
void FindInDegree(ALGragh G)//求出各顶点的入度存入数组indegree中
{
int i,count;
for(i=0;i<G.vexnum; i++)
{
count=0;
AdjNode *p=G.converse_Vex[i].first;
if(p)
{
while(p)
{
p=p->next;
count++;
}
}
indegree[i]=count;
}
cout<<"入度数组为:"<<endl;
for(int i=0;i<G.vexnum;i++)//输出入度数组
cout<<indegree[i]<<"\t";
cout<<endl;
}
bool TopologicalSort(ALGragh G, int topo[])//拓扑排序
{
//有向图G采用邻接表存储结构
//若G无回路,则生成G的一个拓扑序列topo[]并返回true,否则false
int i,m;
stack<int>S; //初始化一个栈S,需要引入头文件#include<stack>
FindInDegree(G); //求出各顶点的入度存入数组indegree[]中
for(i=0;i<G.vexnum;i++)
if(!indegree[i])//入度为0者进栈
S.push(i);
m=0; //对输出顶点计数,初始为0
while(!S.empty())//栈S非空
{
i=S.top(); //取栈顶顶点i
S.pop(); //栈顶顶点i出栈
topo[m]=i; //将i保存在拓扑序列数组topo中
m++; //对输出顶点计数
AdjNode *p=G.Vex[i].first; //p指向i的第一个邻接点
while(p) //i的所有邻接点入度减1
{
int k=p->v; //k为i的邻接点
--indegree[k]; //i的每个邻接点的入度减1
if(indegree[k]==0) //若入度减为0,则入栈
S.push(k);
p=p->next; //p指向顶点i下一个邻接结点
}
printg(G);
}
if(m<G.vexnum)//该有向图有回路
return false;
else
return true;
}
bool CriticalPath(ALGragh G,int topo[])//G为邻接表存储的有向网,输出G的各项关键活动
{
int n,i,k,j,e,l;
if(TopologicalSort(G,topo))
{
cout<<"拓扑序列为:"<<endl;
for(int i=0;i<G.vexnum;i++)//输出拓扑序列
cout<<topo[i]<<"\t";
cout<<endl;
}
else
cout<<"该图有环,无拓扑序列!"<<endl;
n=G.vexnum; //n为顶点个数
for(i=0;i<n;i++) //给每个事件的最早发生时间置初值0
ve[i]=0;
//按拓扑次序求每个事件的最早发生时间
printg(G);
for(i=0;i<n; i++)
{
k=topo[i]; //取得拓扑序列中的顶点序号k
AdjNode *p=G.Vex[k].first; //p指向k的第一个邻接顶点
while(p!=NULL)
{ //依次更新k的所有邻接顶点的最早发生时间
j=p->v; //j为邻接顶点的序号
if(ve[j]<ve[k]+p->weight) //更新顶点j的最早发生时间ve[j]
ve[j]=ve[k]+p->weight;
p=p->next; //p指向k的下一个邻接顶点
}
}
for(i=0;i<n;i++) //给每个事件的最迟发生时间置初值ve[n-1]
vl[i]=ve[n-1];
//按逆拓扑次序求每个事件的最迟发生时间
for(i=n-1;i>=0;i--)
{
k=topo[i]; //取得逆拓扑序列中的顶点序号k
AdjNode *p=G.Vex[k].first; //p指向k的第一个邻接顶点
while(p!=NULL)
{ //根据k的邻接点,更新k的最迟发生时间
j=p->v; //j为邻接顶点的序号
if(vl[k]>vl[j]-p->weight) //更新顶点k的最迟发生时间vl[k]
vl[k]=vl[j]-p->weight;
p=p->next; //p指向k的下一个邻接顶点
}
}
cout<<"事件的最早发生时间和最迟发生时间:"<<endl;
for(int i=0;i<n;i++)
cout<<ve[i]<<"\t"<<vl[i]<<endl;
//判断每一活动是否为关键活动
cout<<"关键活动路径权值之和为:"<<vl[n-1]<<endl;
cout<<endl;
cout<<"关键活动路径为:";
for(i=0;i<n; i++) //每次循环针对vi为活动开始点的所有活动
{
AdjNode *p=G.Vex[i].first; //p指向i的第一个邻接顶点
while(p!=NULL)
{
j=p->v; //j为i的邻接顶点的序号
e=ve[i]; //计算活动<vi, vj>的最早开始时间e
l=vl[j]-p->weight; //计算活动<vi, vj>的最迟开始时间l
if(e==l) //若为关键活动,则输出<vi, vj>
cout<<"<"<<G.Vex[i].data<<","<<G.Vex[j].data<<"> ";
p=p->next; //p指向i的下一个邻接顶点
}
}
return true;
}
int main()
{
ALGragh G;
int *topo=new int[G.vexnum];
CreateALGraph(G);//创建有向图的邻接表和逆邻接表
printg(G);//输出邻接表和逆邻接表
CriticalPath(G,topo);
return 0;
}
program 8-1-1 SqSearch
#include<iostream>
using namespace std;
#define Maxsize 100
int SqSearch(int r[],int n,int x)//顺序查找
{
for(int i=0;i<n;i++) //要判断i是否超过范围n
if(r[i]==x) //r[i]和x比较
return i;//返回下标
return -1;
}
int SqSearch2(int r2[],int n,int x)//顺序查找优化算法
{
int i;
r2[0]=x;//待查找元素放入r[0],作为监视哨
for(i=n;r2[i]!=x;i--);//不需要判断i是否超过范围
return i;
}
int main()
{
int i,n,x,r[Maxsize],r2[Maxsize+1];
cout<<"请输入元素个数n为:"<<endl;
cin>>n;
cout<<"请依次n个元素:"<<endl;
for(int i=0;i<n;i++)
{
cin>>r[i];
r2[i+1]=r[i];//r2[]数组0空间未用,做监视哨
}
cout<<endl;
cout<<"请输入要查找的元素:";
cin>>x;
//i=SqSearch(r,n,x);
// if(i==-1)
// cout<<"该数列中没有要查找的元素"<<endl;
// else
// cout<<"要查找的元素在第"<<i+1<<"位"<<endl;
i=SqSearch2(r2,n,x);
if(i==0)
cout<<"该数列中没有要查找的元素"<<endl;
else
cout<<"要查找的元素在第"<<i<<"位"<<endl;
return 0;
}
program 8-1-2 BinarySearch
#include<iostream>
#include<cstdlib> //排序sort函数需要该头文件
#include<algorithm>
using namespace std;
const int M=100;
int x,n,i;
int s[M];
int BinarySearch(int s[],int n,int x)//二分查找非递归算法
{
int low=0,high=n-1; //low指向有序数组的第一个元素,high指向有序数组的最后一个元素
while(low<=high)
{
int middle=(low+high)/2; //middle为查找范围的中间值
if(x==s[middle]) //x等于查找范围的中间值,算法结束
return middle;
else if(x>s[middle]) //x大于查找范围的中间元素,则从左半部分查找
low=middle+1;
else //x小于查找范围的中间元素,则从右半部分查找
high=middle-1;
}
return -1;
}
int recursionBS (int s[],int x,int low,int high) //二分查找递归算法
{
//low指向数组的第一个元素,high指向数组的最后一个元素
if(low>high) //递归结束条件
return -1;
int middle=(low+high)/2; //计算middle值(查找范围的中间值)
if(x==s[middle]) //x等于s[middle],查找成功,算法结束
return middle;
else if(x<s[middle]) //x小于s[middle],则从前半部分查找
return recursionBS (s,x,low,middle-1);
else //x大于s[middle],则从后半部分查找
return recursionBS (s,x,middle+1,high);
}
int main()
{
cout<<"该数列中的元素个数n为:";
cin>>n;
cout<<"请依次输入数列中的元素:";
for(i=0;i<n;i++)
cin>>s[i];
sort(s,s+n); //二分查找的序列必须是有序的,如果无序需要先排序
cout<<"排序后的数组为:";
for(i=0;i<n;i++)
cout<<s[i]<<" ";
cout<<endl;
cout<<"请输入要查找的元素:";
cin>>x;
//i=BinarySearch(s,n,x);
i=recursionBS(s,x,0,n-1);
if(i==-1)
cout<<"该数列中没有要查找的元素"<<endl;
else
cout<<"要查找的元素在第"<<i+1<<"位"<<endl;//位序和下标差1
return 0;
}
program 8-2-1 BST
#include<iostream>
using namespace std;
#define ENDFLAG -1
typedef int ElemType;
typedef struct BSTNode{
ElemType data; //结点数据域
BSTNode *lchild,*rchild; //左右孩子指针
}BSTNode,*BSTree;
BSTree SearchBST(BSTree T,ElemType key)//二叉排序树的递归查找
{
//若查找成功,则返回指向该数据元素结点的指针,否则返回空指针
if((!T)|| key==T->data)
return T;
else if (key<T->data)
return SearchBST(T->lchild,key);//在左子树中继续查找
else
return SearchBST(T->rchild,key); //在右子树中继续查找
}
void InsertBST(BSTree &T,ElemType e)//二叉排序树的插入
{
//当二叉排序树T中不存在关键字等于e的数据元素时,则插入该元素
if(!T)
{
BSTree S=new BSTNode; //生成新结点
S->data=e; //新结点S的数据域置为e
S->lchild=S->rchild=NULL;//新结点S作为叶子结点
T=S; //把新结点S链接到已找到的插入位置
}
else if(e<T->data)
InsertBST(T->lchild,e );//插入左子树
else if(e>T->data)
InsertBST(T->rchild,e);//插入右子树
}
void CreateBST(BSTree &T )//二叉排序树的创建
{
//依次读入一个关键字为key的结点,将此结点插入二叉排序树T中
T=NULL;
ElemType e;
cin>>e;
while(e!=ENDFLAG)//ENDFLAG为自定义常量,作为输入结束标志
{
InsertBST(T,e); //插入二叉排序树T中
cin>>e;
}
}
void DeleteBST(BSTree &T,char key)
{
//从二叉排序树T中删除关键字等于key的结点
BSTree p=T;BSTree f=NULL;
BSTree q;
BSTree s;
if(!T) return; //树为空则返回
while(p)//查找
{
if(p->data==key) break; //找到关键字等于key的结点p,结束循环
f=p; //f为p的双亲
if (p->data>key)
p=p->lchild; //在p的左子树中继续查找
else
p=p->rchild; //在p的右子树中继续查找
}
if(!p) return; //找不到被删结点则返回
//三种情况:p左右子树均不空、无右子树、无左子树
if((p->lchild)&&(p->rchild))//被删结点p左右子树均不空
{
q=p;
s=p->lchild;
while(s->rchild)//在p的左子树中继续查找其前驱结点,即最右下结点
{
q=s;
s=s->rchild;
}
p->data=s->data; //s的值赋值给被删结点p,然后删除s结点
if(q!=p)
q->rchild=s->lchild; //重接q的右子树
else
q->lchild=s->lchild; //重接q的左子树
delete s;
}
else
{
if(!p->rchild)//被删结点p无右子树,只需重接其左子树
{
q=p;
p=p->lchild;
}
else if(!p->lchild)//被删结点p无左子树,只需重接其右子树
{
q=p;
p=p->rchild;
}
/*――――――――――将p所指的子树挂接到其双亲结点f相应的位置――――――――*/
if(!f)
T=p; //被删结点为根结点
else if(q==f->lchild)
f->lchild=p; //挂接到f的左子树位置
else
f->rchild=p;//挂接到f的右子树位置
delete q;
}
}
void InOrderTraverse(BSTree &T)//中序遍历
{
if(T)
{
InOrderTraverse(T->lchild);
cout<<T->data<<"\t";
InOrderTraverse(T->rchild);
}
}
int main()
{
BSTree T;
cout<<"请输入一些整型数,-1结束"<<endl;
CreateBST(T);
cout<<"当前有序二叉树中序遍历结果为"<<endl;
InOrderTraverse(T);
cout<<endl;
ElemType key;//待查找或待删除内容
cout<<"请输入待查找关键字"<<endl;
cin>>key;
BSTree result=SearchBST(T,key);
if(result)
cout<<"找到"<<key<<endl;
else
cout<<"未找到"<<key<<endl;
cout<<"请输入待删除关键字"<<endl;
cin>>key;
DeleteBST(T,key);
cout<<"当前有序二叉树中序遍历结果为"<<endl;
InOrderTraverse(T);
return 0;
}
program 8-2-2 AVL
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef struct AVLNode{
int data;
int height;
struct AVLNode *lchild;
struct AVLNode *rchild;
}*AVLTree;
AVLTree Empty(AVLTree &T)//删除树
{
if(T==NULL) return NULL;
Empty(T->lchild);
Empty(T->rchild);
delete T;
return NULL;
}
inline int Height(AVLTree T)//计算高度
{
if(T==NULL) return 0;
return T->height;
}
void updateHeight(AVLTree &T)
{
T->height=max(Height(T->lchild),Height(T->rchild))+1;
}
AVLTree LL_Rotation(AVLTree &T)//LL旋转
{
AVLTree temp=T->lchild;
T->lchild=temp->rchild;
temp->rchild=T;
updateHeight(T);//更新高度
updateHeight(temp);
return temp;
}
AVLTree RR_Rotation(AVLTree &T)//RR旋转
{
AVLTree temp=T->rchild;
T->rchild=temp->lchild;
temp->lchild=T;
updateHeight(T);//更新高度
updateHeight(temp);
return temp;
}
AVLTree LR_Rotation(AVLTree &T)//LR旋转
{
T->lchild=RR_Rotation(T->lchild);
return LL_Rotation(T);
}
AVLTree RL_Rotation(AVLTree &T)//RL旋转
{
T->rchild=LL_Rotation(T->rchild);
return RR_Rotation(T);
}
AVLTree Insert(AVLTree &T,int x)
{
if(T==NULL) //如果为空,创建新结点
{
T=new AVLNode;
T->lchild=T->rchild=NULL;
T->data=x;
T->height=1;
return T;
}
if(T->data==x) return T;//查找成功,什么也不做,查找失败时才插入
if(x<T->data)//插入到左子树
{
T->lchild=Insert(T->lchild,x);//注意插入后饭后结果挂接到T->lchild
if(Height(T->lchild)-Height(T->rchild)==2)//插入后看是否平衡,如果不平衡显然是插入的那一边高度大
{ //沿着高度大的那条路径判断
if(x<T->lchild->data)//判断是LL还是LR,即插入的是lchild节点的lchild 还是rchild
T=LL_Rotation(T);
else
T=LR_Rotation(T);
}
}
else//插入到右子树
{
T->rchild=Insert(T->rchild,x);
if(Height(T->rchild)-Height(T->lchild)==2)
{
if(x>T->rchild->data)
T=RR_Rotation(T);
else
T=RL_Rotation(T);
}
}
updateHeight(T);
return T;
}
AVLTree adjust(AVLTree &T)//删除结点后,需要判断是否还是平衡,如果不平衡,就要调整
{
if(T==NULL) return NULL;
if(Height(T->lchild)-Height(T->rchild)==2)//沿着高度大的那条路径判断
{
if(Height(T->lchild->lchild)>=Height(T->lchild->rchild))
T=LL_Rotation(T);
else
T=LR_Rotation(T);
}
if(Height(T->rchild)-Height(T->lchild)==2)//沿着高度大的那条路径判断
{
if(Height(T->rchild->rchild)>=Height(T->rchild->lchild))
T=RR_Rotation(T);
else
T=RL_Rotation(T);
}
updateHeight(T);
return T;
}
AVLTree Delete(AVLTree &T,int x)
{
if(T==NULL) return NULL;
if(T->data==x)//如果找到删除节点
{
if(T->rchild==NULL)//如果该节点的右孩子为NULL,那么直接删除
{
AVLTree temp=T;
T=T->lchild;
delete temp;
}
else//否则,将其右子树的最左孩子作为这个节点,并且递归删除这个节点的值
{
AVLTree temp;
temp=T->rchild;
while(temp->lchild)
temp=temp->lchild;
T->data=temp->data;
T->rchild=Delete(T->rchild,T->data);
updateHeight(T);
}
return T;
}
if(T->data>x)//调节删除节点后可能涉及的节点
T->lchild=Delete(T->lchild,x);
if(T->data<x)
T->rchild=Delete(T->rchild,x);
updateHeight(T);
T=adjust(T);
return T;
}
void Preorder(AVLTree T)//前序遍历方便看树的结果
{
if(T==NULL) return ;
cout<<T->data<<"\t"<<T->height<<endl;
Preorder(T->lchild);
Preorder(T->rchild);
}
void Inorder(AVLTree T)//中序遍历方便看树的结果
{
if(T==NULL) return ;
Inorder(T->lchild);
cout<<T->data<<"\t"<<T->height<<endl;
Inorder(T->rchild);
}
void Posorder(AVLTree T)//后序遍历方便看树的结果
{
if(T==NULL) return ;
Posorder(T->lchild);
Posorder(T->rchild);
cout<<T->data<<"\t"<<T->height<<endl;
}
void show(AVLTree T)
{
Preorder(T);
cout<<endl;
Inorder(T);
cout<<endl;
Posorder(T);
}
AVLTree CreateAVL(AVLTree &T)
{
int n,x;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>x;
T=Insert(T,x);
}
return T;
}
int main()
{
int x;
AVLTree root=NULL;
root=Empty(root);
CreateAVL(root);
show(root);
cin>>x;
root=Delete(root,x);
show(root);
return 0;
}
program 8-3-1 Hash
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define m 15//哈希表的表长
#define NULLKEY 0//单元为空的标记
int HT[m],HC[m];
int H(int key)//哈希函数
{
return key%13;
}
int Linedetect(int HT[],int H0,int key,int &cnt)
{
int Hi;
for(int i=1;i<m;++i)
{
cnt++;
Hi=(H0+i)%m; //按照线性探测法计算下一个哈希地址Hi
if(HT[Hi]==NULLKEY)
return Hi; //若单元Hi为空,则所查元素不存在
else if(HT[Hi]==key)
return Hi; //若单元Hi中元素的关键字为key
}
return -1;
}
int Seconddetect(int HT[],int H0,int key,int &cnt)
{
int Hi;
for(int i=1;i<=m/2;++i)
{
int i1=i*i;
int i2=-i1;
cnt++;
Hi=(H0+i1)%m; //按照线性探测法计算下一个哈希地址Hi
if(HT[Hi]==NULLKEY)//若单元Hi为空,则所查元素不存在
return Hi;
else if(HT[Hi]==key)//若单元Hi中元素的关键字为key
return Hi;
cnt++;
Hi=(H0+i2)%m; //按照线性探测法计算下一个哈希地址Hi
if(Hi<0)
Hi+=m;
if(HT[Hi]==NULLKEY)//若单元Hi为空,则所查元素不存在
return Hi;
else if(HT[Hi]==key)//若单元Hi中元素的关键字为key
return Hi;
}
return -1;
}
int SearchHash(int HT[],int key)
{
//在哈希表HT中查找关键字为key的元素,若查找成功,返回哈希表的单元标号,否则返回-1
int H0=H(key); //根据哈希函数H(key)计算哈希地址
int Hi,cnt=1;
if(HT[H0]==NULLKEY)//若单元H0为空,则所查元素不存在
return -1;
else if(HT[H0]==key)//若单元H0中元素的关键字为key,则查找成功
{
cout<<"查找成功,比较次数:"<<cnt<<endl;
return H0;
}
else
{
Hi=Linedetect(HT,H0,key,cnt);
if(HT[Hi]==key)//若单元Hi中元素的关键字为key,则查找成功
{
cout<<"查找成功,比较次数:"<<cnt<<endl;
return Hi;
}
else
return -1; //若单元Hi为空,则所查元素不存在
}
}
bool InsertHash(int HT[],int key)
{
int H0=H(key); //根据哈希函数H(key)计算哈希地址
int Hi=-1,cnt=1;
if(HT[H0]==NULLKEY)
{
HC[H0]=1;//统计比较次数
HT[H0]=key; //若单元H0为空,放入
return 1;
}
else
{
Hi=Linedetect(HT,H0,key,cnt);//线性探测
//Hi=Seconddetect(HT,H0,key,cnt);//二次探测
if((Hi!=-1)&&(HT[Hi]==NULLKEY))
{
HC[Hi]=cnt;
HT[Hi]=key;//若单元Hi为空,放入
return 1;
}
}
return 0;
}
void print(int HT[])
{
for(int i=0;i<m;i++)
cout<<HT[i]<<"\t";
cout<<endl;
}
int main()
{
int x;
memset(HT,0,sizeof(HT));
memset(HC,0,sizeof(HC));
print(HT);
cout<<"输入12个关键字,存入哈希表中:"<<endl;
for(int i=0;i<12;i++)
{
cin>>x;//14 36 42 38 40 15 19 12 51 65 34 25
if(!InsertHash(HT,x))
{
cout<<"创建哈希表失败!"<<endl;
return 0;
}
}
cout<<"输出哈希表:"<<endl;
print(HT);
print(HC);
cout<<"输入要查找的关键字"<<endl;
cin>>x;
int result=SearchHash(HT,x);
if(result!=-1)
cout<<"在第"<<result+1<<"位置找到"<<endl;
else
cout<<"未找到"<<endl;
return 0;
}
program 9-1-1 StraightInsertSort
#include<iostream>
using namespace std;
#define Maxsize 100
void StraightInsertSort(int r[],int n) //直接插入排序
{
int i,j;
for(i=2;i<=n;i++) //r[i]插入有序子表
if(r[i]<r[i-1]) //r[i]和前一个元素r[i-1]比较
{
r[0]=r[i]; //r[i]暂存到r[0]中,r[0]有监视哨的作用
r[i]=r[i-1]; //r[i-1]后移一位
for(j=i-2;r[j]>r[0];j--) //从后向前寻找插入位置,逐个后移,直到找到插入位置
r[j+1]=r[j]; //r[j]后移一位
r[j+1]=r[0]; //将r[0]插入到r[j+1]位置
}
}
int main()
{
int i,n,r[Maxsize+1];
cout<<"请输入数列中的元素个数n为:"<<endl;
cin>>n;
cout<<"请依次输入数列中的元素:"<<endl;
for(i=1;i<=n;i++)
cin>>r[i];
StraightInsertSort(r,n);
cout<<"直接插入排序结果:"<<endl;
for(i=1;i<=n;i++)
cout<<r[i]<<" ";
return 0;
}
program 9-1-2 ShellSort
#include<iostream>
using namespace std;
#define Maxsize 100
void ShellInsert(int r[],int n,int dk) //直接插入排序
{
int i,j;
for(i=dk+1;i<=n;i++) //r[i]插入有序子表
if(r[i]<r[i-dk]) //r[i]和前一个元素r[i-dk]比较
{
r[0]=r[i]; //r[i]暂存到r[0]中,r[0]有监视哨的作用
for(j=i-dk;j>0&&r[j]>r[0];j-=dk) //从后向前寻找插入位置,逐个后移,直到找到插入位置
r[j+dk]=r[j]; //r[j]后移dk位
r[j+dk]=r[0]; //将r[0]插入到r[j+dk]位置
}
}
void ShellSort(int r[],int n,int dt[],int t) //按增量序列dt[0..t-1]对顺序表L作t趟希尔排序
{
for(int k=0;k<t;k++)
{
ShellInsert(r,n,dt[k]); //一趟增量为dt[k]的希尔插入排序
for(int i=1;i<=n;i++) //测试每趟排序结果
cout<<r[i]<<" ";
cout<<endl;
}
}
int main()
{
int i,n,t,r[Maxsize+1],dt[Maxsize];
cout<<"请输入数列中的元素个数n为:"<<endl;
cin>>n;
cout<<"请依次输入数列中的元素:"<<endl;
for(i=1;i<=n;i++)
cin>>r[i];
cout<<"请输入增量个数:"<<endl;
cin>>t;
cout<<"请依次输入增量:"<<endl;
for(i=0;i<t;i++)
cin>>dt[i];
ShellSort(r,n,dt,t);
cout<<"希尔排序结果:"<<endl;
for(i=1;i<=n;i++)
cout<<r[i]<<" ";
return 0;
}
program 9-2-1 BubbleSort
#include<iostream>
using namespace std;
#define Maxsize 100
void BubbleSort(int r[],int n) //冒泡排序
{
int i,j,temp;
bool flag;
i=n-1;
flag=true;
while(i>0&&flag)
{
flag=false;
for(j=0;j<i;j++) //进行一趟排序
if(r[j]>r[j+1])
{
flag=true;
temp=r[j]; //交换两个记录
r[j]=r[j+1];
r[j+1]=temp;
}
for(j=0;j<=i;j++)//测试每趟排序结果
cout<<r[j]<<" ";
cout<<endl;
i--;
}
}
int main()
{
int i,n,r[Maxsize];
cout<<"请输入数列中的元素个数n为:"<<endl;
cin>>n;
cout<<"请依次输入数列中的元素:"<<endl;
for(i=0;i<n;i++)
cin>>r[i];
BubbleSort(r,n);
cout<<"冒泡排序结果:"<<endl;
for(i=0;i<n;i++)
cout<<r[i]<<" ";
return 0;
}
program 9-2-2 QuickSort
#include<iostream>
using namespace std;
int Partition(int r[],int low,int high)//划分函数
{
int i=low,j=high,pivot=r[low];//基准元素
while(i<j)
{
while(i<j&&r[j]>pivot) j--;//向左扫描
if(i<j)
swap(r[i++],r[j]);//r[i]和r[j]交换后i+1右移一位
while(i<j&&r[i]<=pivot) i++;//向右扫描
if(i<j)
swap(r[i],r[j--]);//r[i]和r[j]交换 后j-1左移一位
}
return i;//返回最终划分完成后基准元素所在的位置
}
int Partition2(int r[],int low,int high)//划分函数
{
int i=low,j=high,pivot=r[low];//基准元素
while(i<j)
{
while(i<j&&r[j]>pivot) j--;//向左扫描
while(i<j&&r[i]<=pivot) i++;//向右扫描
if(i<j)
swap(r[i++],r[j--]);//r[i]和r[j]交换
}
if(r[i]>pivot)
{
swap(r[i-1],r[low]);//r[i-1]和r[low]交换
return i-1;//返回最终划分完成后基准元素所在的位置
}
swap(r[i],r[low]);//r[i]和r[low]交换
return i;//返回最终划分完成后基准元素所在的位置
}
void QuickSort(int R[],int low,int high)//实现快排算法
{
int mid;
if(low<high)
{
mid=Partition(R,low,high); //基准位置
// for(int i=low;i<=high;i++)
// cout<<R[i]<<" ";
// cout<<endl;
QuickSort(R,low,mid-1);//左区间递归快排
QuickSort(R,mid+1,high);//右区间递归快排
}
}
int main()
{
int a[100];
int i,n;
cout<<"请先输入要排序的数据的个数:";
cin>>n;
cout<<"请输入要排序的数据:";
for(i=0;i<n;i++)
cin>>a[i];
cout<<endl;
QuickSort(a,0,n-1);
cout<<"排序后的序列为:"<<endl;
for(i=0;i<n;i++)
cout<<a[i]<<" " ;
cout<<endl;
return 0;
}
program 9-3-1 SimpleSelectSort
#include<iostream>
using namespace std;
#define Maxsize 100
void SimpleSelectSort(int r[],int n) //简单选择排序
{
int i,j,k,temp;
for(i=0;i<n-1;i++)//n-1趟排序
{
k=i;
for(j=i+1;j<n;j++)//找最小值
if(r[j]<r[k])
k=j; //记录最小值下标
if(k!=i)
{
temp=r[i];// r[i]与r[k]交换
r[i]=r[k];
r[k]=temp;
}
for(j=0;j<n;j++)//测试每趟排序结果
cout<<r[j]<<" ";
cout<<endl;
}
}
int main()
{
int i,n,r[Maxsize];
cout<<"请输入数列中的元素个数n为:"<<endl;
cin>>n;
cout<<"请依次输入数列中的元素:"<<endl;
for(i=0;i<n;i++)
cin>>r[i];
SimpleSelectSort(r,n);
cout<<"简单选择排序结果:"<<endl;
for(i=0;i<n;i++)
cout<<r[i]<<" ";
return 0;
}
program 9-3-2 HeapSort
#include<iostream>
using namespace std;
#define maxN 1000
int r[maxN];
void Sink(int k,int n)//下沉操作
{
while(2*k<=n)//如果有左孩子
{
int j=2*k;//j指向左孩子
if(j<n&&r[j]<r[j+1])//如果有右孩子且左孩子比右孩子小
j++; //j指向右孩子
if(r[k]>=r[j])//比较大的孩子大
break; //已满足堆
else
swap(r[k],r[j]);//与较大的孩子交换
k=j;//k指向交换后的新位置,继续向下比较,一直下沉到叶子
}
}
void CreatHeap(int n)//构建初始堆
{
for(int i=n/2;i>0;i--)//从最后一个分支结点n/2开始调整为堆,直到第一个结点
Sink(i,n);
}
void HeapSort(int n)//堆排序
{
CreatHeap(n);//构建初始堆
while(n>1)
{
swap(r[1],r[n--]);//堆顶和最后一个记录交换,交换后n减1
Sink(1,n);//堆顶下沉
}
}
void print(int n)//输出
{
for(int i=1;i<=n;i++)
cout<<r[i]<<"\t";
cout<<endl;
}
int main()
{
int n;
cout<<"请输入待排序记录个数:"<<endl;
cin>>n;
cout<<"请输入n个整数:"<<endl;
for(int i=1;i<=n;i++)
cin>>r[i];
HeapSort(n);//堆排序
print(n);
return 0;
}
program 9-4 MergeSort
#include<iostream>
using namespace std;
void Merge(int A[],int low,int mid,int high)//合并函数
{
int *B=new int[high-low+1];//申请一个辅助数组
int i=low,j=mid+1,k=0;
while(i<=mid&&j<=high) {//按从小到大存放到辅助数组B[]中
if(A[i]<=A[j])
B[k++]=A[i++];
else
B[k++]=A[j++];
}
while(i<=mid) B[k++]=A[i++];//将数组中剩下的元素放置B中
while(j<=high) B[k++]=A[j++];
for(i=low,k=0;i<=high;i++)
A[i]=B[k++];
delete []B;//释放空间
}
void MergeSort(int A[],int low,int high)//合并排序
{
if(low<high)
{
int mid=(low+high)/2;//取中点
MergeSort(A,low,mid);//对A[low:mid]中的元素合并排序
MergeSort(A,mid+1,high);//对A[mid+1:high]中的元素合并排序
Merge(A,low,mid,high);//合并
}
}
int main()
{
int n, A[100];
cout<<"请输入数列中的元素个数n为:"<<endl;
cin>>n;
cout<<"请依次输入数列中的元素:"<<endl;
for(int i=0;i<n;i++)
cin>>A[i];
MergeSort(A,0,n-1);
cout<<"合并排序结果:"<<endl;
for(int i=0;i<n;i++)
cout<<A[i]<<" ";
cout<<endl;
return 0;
}
program 9-5-2 RadixSort
#include<iostream>
#define Maxsize 10000
using namespace std;
int A[Maxsize];
int Maxbit(int A[],int n)//求待排序序列最大元素位数
{
int maxvalue=A[0],digits=0;//初始化最大元素为A[0],最大位数为0
for(int i=1;i<n;i++) //找到序列中最大元素
if(A[i]>maxvalue)
maxvalue=A[i];
while(maxvalue!=0)//分解得到最大元素的位数
{
digits++;
maxvalue/=10;
}
return digits;
}
int Bitnumber(int x,int bit)//求x第bit位上的数字,例如238第2位上的数字为3
{
int temp=1;
for(int i=1;i<bit;i++)
temp*=10;
return (x/temp)%10;
}
void RadixSort(int A[],int n)//基数排序
{
int i,j,k,bit,maxbit;
maxbit=Maxbit(A,n);//求最大元素位数
cout<<maxbit<<endl;
int **B=new int *[10];
for(i=0;i<10;i++)
B[i]=new int[n+1];
for(i=0;i<10;i++)
B[i][0]=0;//统计第i个桶的元素个数
//从个位到高位,对不同的位数进行桶排序
for(bit=1;bit<=maxbit;bit++)
{
for(j=0;j<n;j++)//分配
{
int num=Bitnumber(A[j],bit);//取A[j]第bit位上的数字
int index=++B[num][0];
B[num][index]=A[j];
}
for(i=0,j=0;i<10;i++)//收集
{
for(k=1;k<=B[i][0];k++)
A[j++]=B[i][k];
B[i][0]=0;//收集后元素个数置零
}
}
for(int i=0;i<10;i++)
delete []B[i];
delete B;
}
int main()
{
int n;
cout<<"请输入数列中的元素个数n为:"<<endl;
cin>>n;
cout<<"请依次输入数列中的元素:"<<endl;
for(int i=0;i<n;i++)
cin>>A[i];
RadixSort(A,n);
cout<<"基数排序结果:"<<endl;
for(int i=0;i<n;i++)
cout<<A[i]<<" ";
cout<<endl;
return 0;
}
program 10-1 UnionFind
#include<iostream>
#include<algorithm>
using namespace std;
const int N=100;
int father[N];
int n, m;
void Init(int n)//初始化
{
for(int i=1;i<=n;i++)
father[i]=i;
}
int Find(int x)//找祖宗
{
if(x!=father[x])
father[x]=Find(father[x]);
return father[x];
}
int Merge(int a,int b)//合并集合
{
int p=Find(a);
int q=Find(b);
if(p==q) return 0;
if(p>q)
father[p]=q;//小的赋值给大的集合号
else
father[q]=p;
return 1;
}
int main()
{
int sum=0,u,v;
cout<<"输入人数n和亲戚关系数m:"<<endl;
cin>>n>>m;
Init(n);
cout<<"输入有亲戚关系的两个人编号u,v"<<endl;
for(int i=1;i<=m;i++)
{
cin>>u>>v;
Merge(u,v);
}
for(int i=1;i<=n;i++)//测试
cout<<father[i];
for(int i=1;i<=n;i++)//输出有多少个家族
if(father[i]==i)
sum++;
cout<<"家族数为:"<<sum<<endl;
return 0;
}
program 10-2 PriorityQueue
#include<iostream>
using namespace std;
#define maxN 1000
int r[maxN];
void Sink(int k,int n)//下沉操作
{
while(2*k<=n)//如果有左孩子
{
int j=2*k;//j指向左孩子
if(j<n&&r[j]<r[j+1])//如果有右孩子且左孩子比右孩子小
j++; //j指向右孩子
if(r[k]>=r[j])//比较大的孩子大
break; //已满足堆
else
swap(r[k],r[j]);//与较大的孩子交换
k=j;//k指向交换后的新位置,继续向下比较,一直下沉到叶子
}
}
void Swim(int k)//上浮操作
{
while(k>1&&r[k]>r[k/2])//如果大于双亲
{
swap(r[k],r[k/2]);//与双亲交换
k=k/2;//k指向交换后的新位置,继续向上比较,一直上浮到根
}
}
void CreatHeap(int n)//构建初始堆
{
for(int i=n/2;i>0;i--)//从最后一个分支结点n/2开始下沉调整为堆,直到第一个结点
Sink(i,n);
}
void push(int n,int x)//入队
{
r[++n]=x;//n加1后,将新元素放入尾部
Swim(n);//最后一个元素上浮操作
}
void pop(int n)//出队
{
cout<<r[1]<<endl;//输出堆顶
r[1]=r[n--];//最后一个元素代替堆顶,n减1
Sink(1,n);//堆顶下沉操作
}
int main()
{
int n,select,x;
cout<<"请输入待排序记录个数:"<<endl;
cin>>n;
cout<<"请输入n个整数:"<<endl;
for(int i=1;i<=n;i++)
cin>>r[i];
CreatHeap(n);//创建初始堆
while(true)
{
cout<<"请选择数字:1.入队;2.出队;0.退出"<<endl;
cin>>select;
switch(select)
{
case 1:
cout<<"输入入队元素:"<<endl;
cin>>x;
push(n,x);//入队
break;
case 2:
pop(n);//出队
break;
case 0:
return 0;
}
}
return 0;
}