趣学数据结构 代码 自用

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值