一:线性表
1.单链表应用
例子一:尾插入创立单链表,并且删除相同元素,即表示一个集合
#include<iostream>
using namespace std;
struct node
{
int num;
struct node *next;
};
node *head;
void creat_list()
{
int N,i;
cin>>N;
node*temp,*tail;
head=new node;
tail=head;
tail->next=NULL;
for(i=0;i<=N-1;i++)
{
temp=new node;
if(temp==NULL)
{
cout<<"memory allocate fail and exit";
exit(1);
}
cin>>temp->num;
tail->next=temp;
tail=temp;
tail->next=NULL;
}
}
void out_put_list()
{
node* a=head->next;
while(a!=NULL)
{
cout<<a->num<<" ";
a=a->next;
}
cout<<endl;
}
void delete_list()
{
node *p,*q,*r;
p=head->next;
while(p)
{
q=p;
while(q->next)
{
if((q->next)->num==p->num)
{
r=q->next;
q->next=r->next;
free(r);
}
else q=q->next;
}
p=p->next;
}
}
int main(void)
{
creat_list();
out_put_list();
delete_list();
out_put_list();
return 0;
}
例题二:把单链表L的元素按类型分为三个单链表
#include<iostream>
#include <ctype.h>
using namespace std;
typedef struct Lnode{
char data;
struct Lnode *next;
}Lnode,*LinkList;
typedef struct List{
LinkList head;
int n;
}List;
void InitLinkList(List &l)
{
l.head=new Lnode;
l.head->next=NULL;
l.n=0;
}//InitLinkList
void CreateLinkList(List &l)
{
cout<<"请输入链表的元素个数:";
cin>>l.n;
cout<<"请输入链表的元素:";
LinkList q=l.head;
for(int i=0;i<l.n;i++)
{
LinkList p=new Lnode;
cin>>p->data;
q->next=p;
q=p;
}
q->next=NULL;
}//CreateLinkList
void SplitLinkList(List &l,List &a,List &b,List &c)
{
LinkList s=l.head->next;
LinkList p=a.head;
LinkList q=b.head;
LinkList r=c.head;
while(s)
{
if(isalpha(s->data))
{
p->next=s;
p=s;
a.n++;
}
else if(isdigit(s->data))
{
q->next=s;
q=s;
b.n++;
}
else{
r->next=s;
r=s;
c.n++;
}
s=s->next;
}
p->next=NULL;
q->next=NULL;
r->next=NULL;
delete []l.head;
}//SplitLinkList
void ShowLinkList(List l)
{
cout<<"该链表的元素个数:"<<l.n<<endl;
cout<<"该链表的元素:";
LinkList p=l.head->next;
while(p)
{
cout<<p->data;
p=p->next;
}
cout<<endl;
}//ShowLinkList
int main(){
List l;
InitLinkList(l);
CreateLinkList(l);
List Sq1,Sq2,Sq3;//字母,数字,其他
InitLinkList(Sq1);
InitLinkList(Sq2);
InitLinkList(Sq3);
SplitLinkList(l,Sq1,Sq2,Sq3);
cout<<"字母字符链表如下:"<<endl;
ShowLinkList(Sq1);
cout<<"数字字符链表如下:"<<endl;
ShowLinkList(Sq2);
cout<<"其他字符链表如下:"<<endl;
ShowLinkList(Sq3);
return 0;
}
例子三:用拷贝构造函数及构造函数创建单链表,并逆序创建单链表
#include<iostream>
#include<iomanip>
using namespace std;
struct node
{
int score;
char num[15];
char name[20];
node *next;
};
class linklist{
private:
node *head;
node *tail;
int length;
public:
linklist(int m)
{
length=m;
head=new node;
head->next=NULL;
tail=head;
cout<<"Input "<<length<<" students'imformation of linklist you want:"<<endl;
cout<<left<<setw(20)<<"name"<<left<<setw(20)<<"num"
<<left<<setw(20)<<"score"<<endl;
int i;
for(i=0;i<=length-1;i++)
{
node *temp=new node;
cin>>temp->name>>temp->num>>temp->score;
temp->next=NULL;
tail->next=temp;
tail=temp;
}
}
void show()
{
if(length==0)
cout<<"It's an empty linklist!"<<endl;
else
{
node *t=head->next;
cout<<"Output "<<length<<" students'imformation of linklist:"<<endl;
cout<<left<<setw(20)<<"name"<<left<<setw(20)<<"num"
<<left<<setw(20)<<"score"<<endl;
while(t!=NULL)
{
cout<<left<<setw(20)<<t->name<<left<<setw(20)<<t->num
<<left<<setw(20)<<t->score<<endl;
t=t->next;
}
}
}
linklist(const linklist &s)
{
length=s.length;
head=new node;
head->next=NULL;
tail=head;
node *t=s.head->next;
while(t!=NULL)
{
node *temp=new node;
strcpy(temp->name,t->name);
strcpy(temp->num,t->num);
temp->score=t->score;
temp->next=NULL;
tail->next=temp;
tail=temp;
t=t->next;
}
}
~linklist()
{
node *r,*p;
if(length==0) delete head;
else
{
p=head->next;
while(head->next!=NULL)
{
r=p;
head->next=r->next;
delete r;
p=head->next;
}
delete head;
}
cout<<"delete....!"<<endl;
}
linklist()
{
head=new node;
head->next=NULL;
tail=head;
node *temp=new node;
strcpy(temp->name,"xiaodong");
strcpy(temp->num,"0825121006");
temp->score=85;
temp->next=NULL;
tail->next=temp;
tail=temp;
length=1;
}
void reverse_linklist()
{
node *q=head->next;
node *r=head;
node *s;
while(q->next!=NULL)
{
node *p=head;
while((p->next)->next!=NULL)
p=p->next;
s=r->next;
r->next=p->next;
(p->next)->next=s;
p->next=NULL;
r=r->next;
}
}
};
int main()
{
linklist list(5);
list.show();
linklist mylist(list);
mylist.show();
linklist youlist;
youlist.show();
list.reverse_linklist();
list.show();
return 0;
}
例子四:约瑟夫环顺序表实现代码
#include<stdio.h>
#include<stdlib.h>
#define LIST_INIT_SIZE 100
#define LISTINCREMENT 10
typedef struct{
int ID;
int Code;
}ElemType;
typedef struct{
ElemType *elem;
int length;
int listsize;
}SqList;
void InitList_Sq(SqList &L){
L.elem=(ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType)); //申请结点空间
if(!L.elem) exit(0); //申请失败,关闭程序
L.length=0; //空表长度为0
L.listsize=LIST_INIT_SIZE; //初始存储容量
}//InitList_Sq
void CreateList_Sq(SqList &L,int n){
if(n>L.listsize){ //判断存储空间是否足够
ElemType *base=(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType));
if(!base) exit(0); //不够再分配
L.elem=base; //指针指向新分配空间的首地址
L.listsize+=LISTINCREMENT; //修改存储容量
}
printf("请输入这%d人的密码(>0):",n);
for(int i=0;i<n;i++){
L.elem[i].ID=i+1;
scanf("%d",&(L.elem[i].Code)); //输入n个人的密码
}
L.length+=n; //修改表长度
}//CreateList_Sq
void DeleteList_Sq(SqList &L,int &m,int &start_pos){ //start_pos为新一轮报数的首个元素的下标
m=(start_pos+m)%L.length; //用取余数的方法寻找报数为m的元素,可减少搜索的次数
if(m==0) m=L.length; //如果报数为m的元素是数组的最后一个元素,要加上表的本身长度
start_pos=m-1; //记录下一轮开始报数的首元素的数组下标
ElemType *q=L.elem+L.length-1; //q指向最后一个元素
ElemType *p=&(L.elem[m-1]); //p指向报数为m的元素
printf("%d ",p->ID); //打印删除元素的编号,即出列编号
m=p->Code; //保存下一轮报数的密码
for(;p<q;p++) *p=*(p+1); //左移覆盖
--L.length; //修改表长
}//DeleteList_Sq
int main(){
SqList L;
int n,m,start_pos(0); //start_pos为新一轮报数的首元素的下标,初始化为0
printf("请输入初始报数(m>0):");
scanf("%d",&m);
while(m<=0){ //检查报数的合法性
printf("请重新输入初始报数(m>0):");
scanf("%d",&m);
}
printf("请输入用户数(0<n):");
scanf("%d",&n);
while(n<=0){ //检查用户数的合法性
printf("请重新输入用户数(n>0):");
scanf("%d",&n);
}
InitList_Sq(L); //初始化顺序表
CreateList_Sq(L,n); //创建顺序表
for(int i=n;i>=1;i--) //根据报数,删除报数为m的元素,并输出出列编号,
DeleteList_Sq(L,m,start_pos); //循环n次,即删除所有元素,顺序表为空时停止循环
printf("/n");
return 0;
}//main
例子五:约瑟夫环循环链表实现代码
#include<stdio.h>
#include<stdlib.h>
typedef struct{
int ID;
int Code;
}ElemType;
typedef struct Lnode{
ElemType elem;
struct Lnode *next;
}Lnode,*LinkList;
void CreateList_L(LinkList &L,int n){
L=(LinkList)malloc(sizeof(Lnode)); //申请结点空间
if(!L) exit(0); //申请失败,关闭程序
LinkList p=L;
printf("请输入这%d人的密码:",n);
for(int i=1;i<=n;i++){
p->elem.ID=i; //为这n个人编号
scanf("%d",&(p->elem.Code)); //输入每个人的密码
if(i==n) break; //如果i等于第n个人,无需再申请结点空间,跳出循环
p->next=(LinkList)malloc(sizeof(Lnode)); //申请下一个结点空间
if(!(p->next)) exit(0); //如果申请失败,关闭程序
p=p->next; //指针移动到下一个结点
}
p->next=L; //首尾相连,构成循环链表
}//CreateList_L
void DeleteList_L(LinkList &L,int &m,int Length){
int j=m%Length; //用取余数的方法寻找报数为m的结点,可减少循环
//遍历的次数
if(j==0||j==1) j+=Length; //如果m是首结点或是尾结点,要加上链表的本身长
//度,目的是寻找报数为m-1的结点,删除m结点就比较方便
int i=1;
while(i++<j-1) L=L->next; //寻找要删除结点的前驱结点
m=L->next->elem.Code; //先保存下一轮报数的密码
printf("%d ",L->next->elem.ID); //打印删除结点的编号,即出列编号
LinkList p=L->next; //保存要删除结点的地址
L->next=p->next; //断开删除结点,即出列,重新连接链表
L=L->next; //移动指针到下一个结点,等待下一轮新的报数
free(p); //删除报数为m的结点
}//DeleteList_L
void main(){
LinkList L=NULL; //初始化为空链表
int n,m;
printf("请输入初始报数(m>0):");
scanf("%d",&m);
while(m<=0){ //检查报数的合法性
printf("请重新输入初始报数(m>0):");
scanf("%d",&m);
}
printf("请输入用户数(0<n):");
scanf("%d",&n);
while(n<=0){ //检查用户数的合法性
printf("请重新输入用户数(n>0):");
scanf("%d",&n);
}
CreateList_L(L,n); //创建循环链表
for(int i=n;i>=1;i--) //根据报数,删除结点,输出出列编号,
DeleteList_L(L,m,i); //循环n次,即删除所有结点,链表为空时停止循环
printf("/n");
}//main
例子六:单链表建立及按顺序输出
#include<iostream>
#include<cstdlib>
using namespace std;
struct node
{
int data;
struct node *next;
};
void main(void)
{
const int N=10;
node *head,*temp,*tail;
head=new node;
head->next=NULL;
tail=head;
for(int i=0;i<=N-1;i++)
{
temp=new node;
if(temp==NULL)
{
cout<<"memory allocate fail and exit";
exit(1);
}
cin>>temp->data;
temp->next=NULL;
tail->next=temp;
tail=temp;
}
head=head->next;
int t;
node *p;
for(i=0;i<=N-2;i++)
{
for(int j=0;j<=N-i-2;j++)
{
if(head->data<(head->next)->data)
{
t=(head->next)->data;
(head->next)->data=head->data;
head->data=t;
}
if(j==0)
p=head;
head=head->next;
}
head=p;
}
while(head!=NULL)
{
cout<<head->data<<" ";
head=head->next;
}
cout<<endl;
}
例子七:建立单循环链表,并连接两个单循环链表
#include<iostream>
using namespace std;
struct node{
int data;
node *next;
};
class linklist{
private:
node *head;
node *rear;
int length;
public:
linklist(int n){
length=n;
head=new node;
head->next=head;
rear=head;
int i;
for(i=0;i<=length-1;++i){
node *temp=new node;
cin>>temp->data;
temp->next=head;
rear->next=temp;
rear=temp;
}
}
void show(){
node *s=head->next;
while(s!=head){
cout<<s->data<<" ";
s=s->next;
}
cout<<endl;
}
~linklist(){
if(length==0)
delete head;
else{
node *r;
while(head->next!=head){
r=head->next;
head->next=r->next;
delete r;
}
delete head;
}
cout<<"delete..........!"<<endl;
}
void connect_list(linklist &l){
node *front=new node;
front->next=front;
node *tail=front;
node *p=l.head->next;
while(p!=l.head){
node *temp=new node;
temp->data=p->data;
temp->next=front;
tail->next=temp;
tail=temp;
p=p->next;
}
rear->next=front->next;
tail->next=head;
delete front;
}
};
int main()
{
linklist a(4);
a.show();
linklist b(5);
b.show();
b.connect_list(a);
b.show();
return 0;
}
例子八:两个单链表互相连接
#include<iostream>
using namespace std;
struct node {
int data;
node *next;
};
class linklist {
private:
node *head;
node *rear;
int length;
public:
linklist(int n){
length=n;
head=new node;
head->next=NULL;
rear=head;
int i;
for(i=0;i<=length-1;++i){
node *temp=new node;
cin>>temp->data;
temp->next=NULL;
rear->next=temp;
rear=temp;
}
}
void show(){
node *s=head->next;
while(s!=NULL){
cout<<s->data<<" ";
s=s->next;
}
cout<<endl;
}
~linklist(){
if(length==0)
delete head;
else{
node *r;
while(head->next!=NULL){
r=head->next;
head->next=r->next;
delete r;
}
delete head;
}
cout<<"delete..........!"<<endl;
}
void connect_list(linklist &l){
node *h=new node;
h->next=NULL;
node *tail=h;
node *p=l.head->next;
while(p!=NULL){
node *temp=new node;
temp->data=p->data;
temp->next=NULL;
tail->next=temp;
tail=temp;
p=p->next;
}
rear->next=h->next;
delete h;
}
linklist(const linklist &l){
head=new node;
head->next=NULL;
rear=head;
node *p=l.head->next;
while(p!=NULL){
node *temp=new node;
temp->data=p->data;
temp->next=NULL;
rear->next=temp;
rear=temp;
p=p->next;
}
}
};
int main(){
linklist a(3);
a.show();
linklist b(5);
b.show();
linklist c(a);
a.connect_list(b);
a.show();
b.connect_list(c);
b.show();
return 0;
}
例子九:双向链表的头插入建表
#include<iostream>
using namespace std;
struct node{
int data;
node *next;
node *prior;
};
class linklist{
private:
node *head;
node *rear;
int length;
public:
linklist(int n){
length=n;
head=new node;
head->next=NULL;
rear=head;
node *temp=new node;
cin>>temp->data;
temp->prior=head;
temp->next=NULL;
head->next=temp;
rear=temp;
node *s=temp;
int i;
for(i=0;i<=length-2;++i){
node *temp=new node;
cin>>temp->data;
head->next=temp;
temp->prior=head;
temp->next=s;
s->prior=temp;
s=s->prior;
}
}
void show(){
node *s=head->next;
while(s!=NULL){
cout<<s->data<<" ";
s=s->next;
}
cout<<endl;
}
void display(){
node *s=rear;
while(s!=head){
cout<<s->data<<" ";
s=s->prior;
}
cout<<endl;
}
/*
~linklist(){
if(length==0)
delete head;
else{
node *r;
while(head->next!=NULL){
r=head->next;
head->next=r->next;
delete r;
}
delete head;
}
cout<<"delete..........!"<<endl;
}*/
//也可以从尾结点开始删除结点
~linklist(){
if(length==0)
delete head;
else{
node *r;
while(head->next!=NULL){
r=rear;
r->prior->next=NULL;
rear=rear->prior;
delete r;
}
delete head;
}
cout<<"delete..........!"<<endl;
}
};
int main()
{
linklist a(4);
a.display();
a.show();
return 0;
}
例子十:双向循环链表的建立
#include<iostream>
using namespace std;
struct node{
int data;
node *next;
node *prior;
};
class linklist{
private:
node *head;
node *rear;
int length;
public:
linklist(int n){
length=n;
head=new node;
head->next=head;
head->prior=head;
rear=head;
int i;
for(i=0;i<=length-1;++i){
node *temp=new node;
cin>>temp->data;
temp->next=head;
temp->prior=rear;
rear->next=temp;
head->prior=temp;
rear=temp;
}
}
void show(){
node *s=head->next;
while(s!=head){
cout<<s->data<<" ";
s=s->next;
}
cout<<endl;
}
void display(){
node *s=head->prior;
while(s!=head){
cout<<s->data<<" ";
s=s->prior;
}
cout<<endl;
}
/*
~linklist(){
if(length==0)
delete head;
else{
node *r;
while(head->next!=head){
r=head->next;
head->next=r->next;
delete r;
}
delete head;
}
cout<<"delete..........!"<<endl;
}*/
~linklist(){
if(length==0)
delete head;
else{
node *r;
while(head->prior!=head){
r=head->prior;
head->prior=r->prior;
delete r;
}
delete head;
}
cout<<"delete..........!"<<endl;
}
void connect(linklist &l){
length+=l.length;
node *front=new node;
front->next=front;
front->prior=front;
node *tail=front;
node *p=l.head->next;
while(p!=l.head){
node *temp=new node;
temp->data=p->data;
temp->next=front;
temp->prior=tail;
tail->next=temp;
front->prior=temp;
tail=temp;
p=p->next;
}
rear->next=front->next;
head->prior=tail;
tail->next=head;
front->next->prior=rear;
delete front;
}
void company(linklist &l){
length+=l.length;
node *front=new node;
front->next=front;
front->prior=front;
node *tail=front;
node *p=l.head->prior;
while(p!=l.head){
node *temp=new node;
temp->data=p->data;
temp->next=front;
temp->prior=tail;
tail->next=temp;
front->prior=temp;
tail=temp;
p=p->prior;
}
rear->next=front->next;
head->prior=tail;
tail->next=head;
front->next->prior=rear;
delete front;
}
void joint(linklist &l){
length+=l.length;
node *front=new node;
front->next=front;
front->prior=front;
node *tail=front;
node *p=l.head->next;
while(p!=l.head){
node *temp=new node;
temp->data=p->data;
temp->next=front;
temp->prior=tail;
tail->next=temp;
front->prior=temp;
tail=temp;
p=p->next;
}
head->prior=front->next;
rear->next=tail;
tail->next=rear;
front->next->prior=head;
delete front;
}
/* void output(){
int i;
node *s=head->next;
for(i=0;i<=2;i++) {
cout<<s->data<<" ";
s=s->next;
}
for(i=3;i<=length-1;i++){
cout<<s->data<<" ";
s=s->prior;
}
cout<<endl;
}*/
};
int main()
{
linklist a(4);
a.show();
a.display();
linklist b(5);
b.show();
b.display();
linklist c(3);
c.show();
c.display();
linklist d(3);
d.show();
d.display();
b.connect(a);
b.show();
b.display();
c.company(a);
c.show();
c.display();
// d.joint(a); //output函数的方法不采用,原因如下:
// d.output(); //必须采用分段输出,不然会死循环
return 0; //析构时将只析构尾结点和头结点,将无法清理干净.
}
例子十一:双向循环链表的删除和插入
#include<iostream>
using namespace std;
struct node{
int data;
node *next;
node *prior;
};
class linklist{
private:
node *head;
node *rear;
int length;
public:
linklist(int n){
length=n;
head=new node;
head->next=head;
head->prior=head;
rear=head;
int i;
for(i=0;i<=length-1;++i){
node *temp=new node;
cin>>temp->data;
temp->next=head;
temp->prior=rear;
rear->next=temp;
head->prior=temp;
rear=temp;
}
}
void show(){
node *s=head->next;
while(s!=head){
cout<<s->data<<" ";
s=s->next;
}
cout<<endl;
}
void display(){
node *s=head->prior;
while(s!=head){
cout<<s->data<<" ";
s=s->prior;
}
cout<<endl;
}
/*
~linklist(){
if(length==0)
delete head;
else{
node *r;
while(head->next!=head){
r=head->next;
head->next=r->next;
delete r;
}
delete head;
}
cout<<"delete..........!"<<endl;
}*/
~linklist(){
if(length==0)
delete head;
else{
node *r;
while(head->prior!=head){
r=head->prior;
head->prior=r->prior;
delete r;
}
delete head;
}
cout<<"delete..........!"<<endl;
}
void insert(int m,int elem){
node *s=head;
int i;
if(m>=(length+1/2))
for(i=0;i<=length-m;++i)
s=s->prior;
else
for(i=0;i<=m-1;++i)
s=s->next;
node *temp=new node;
temp->data=elem;
s->prior->next=temp;
temp->prior=s->prior;
temp->next=s;
s->prior=temp;
length++;
}
void deletelist(int m){
node *s=head;
int i;
if(m>=((length+1)/2))
for(i=0;i<=length-m;++i)
s=s->prior;
else
for(i=0;i<=m-1;++i)
s=s->next;
s->prior->next=s->next;
s->next->prior=s->prior;
delete s;
length--;
}
};
int main()
{
linklist a(7);
a.show();
a.insert(3,10);
a.show();
a.deletelist(4);
a.show();
return 0;
}
例子十二:头插入建立单链表
#include<iostream>
using namespace std;
struct node
{
int data;
node *next;
};
class linklist{
private:
node *head;
int length;
public:
linklist(int m)
{
length=m;
head=new node;
head->next=NULL;
node *tail=new node;
cin>>tail->data;
tail->next=NULL;
head->next=tail;
node *s=tail;
int i;
for(i=0;i<=length-2;i++)
{
node *temp=new node;
cin>>temp->data;
head->next=temp;
temp->next=s;
s=temp;
}
}
void display()
{
if(length==0)
cout<<"It's an empty linklist!"<<endl;
else
{
node *p=head->next;
while(p!=NULL)
{
cout<<p->data<<" ";
p=p->next;
}
cout<<endl;
}
}
~linklist()
{
if(length==0)
delete head;
else
{
node *r;
while(head->next!=NULL)
{
r=head->next;
head->next=r->next;
delete r;
}
delete head;
cout<<"delete........!"<<endl;
}
}
};
int main()
{
linklist mylist(5);
mylist.display();
return 0;
}
备注:其他顺序表,单链表,循环链表,双向循环链表的创建,增删改查,两个链表的连接,逆序创建链表等参照数据结构的伪代码和自己理解,适当修改即可用。
二:栈和队列
备注:有现成的模板库可以调用,一般不单独考,可能在非递归,遍历用到栈和队列的操作。
三:树和二叉树
例子一:二叉树三种递归遍历代码
#include<iostream>
using namespace std;
typedef struct node
{
char ch;
struct node *lchild,*rchild;
}*BiTree;
void CreateBiTree(BiTree &T){ //创建二叉树
char ch;
scanf("%c",&ch);
if(ch=='#') T=NULL;
else{
T=new node;
T->ch=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void PreOrder(BiTree T){ //先序递归遍历二叉树
if(T){
printf("%c",T->ch);
if(T->lchild) PreOrder(T->lchild);
if(T->rchild) PreOrder(T->rchild);
}
}
void InOrder(BiTree T){ //中序递归遍历二叉树
if(T){
InOrder(T->lchild);
printf("%c",T->ch);
InOrder(T->rchild);
}
}
void PostOrder(BiTree T){ //后序递归遍历二叉树
if(T){
PostOrder(T->lchild);
PostOrder(T->rchild);
printf("%c",T->ch);
}
}
int main(){
BiTree T;
CreateBiTree(T);
printf("先序遍历结果:");
PreOrder(T);
printf("/n");
printf("中序遍历结果:");
InOrder(T);
printf("/n");
printf("后序遍历结果:");
PostOrder(T);
printf("/n");
return 0;
}
例子二:二叉树四种非递归遍历(其中三种各有三种不同的方法实现)代码
#include<iostream>
#include<stack>
#include<queue>
using namespace std;
typedef struct node
{
char ch;
struct node *lchild,*rchild;
}*BiTree; //二叉树
typedef struct{
BiTree ptr;
int tag; //标志位
}Mark_BiTree; //标志二叉树
void CreateBiTree(BiTree &T){
//先序次序创建二叉树
char ch;
scanf("%c",&ch);
if(ch=='#') T=NULL;
else{
T=new node;
T->ch=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void PreOrder(BiTree T){
//利用栈先序遍历二叉树非递归算法
//方法一:这里采用广度遍历入栈,类似层序遍历,不过是从上到下,从右到左。
stack<BiTree> s; //初始化栈
if(T){
s.push(T); //根结点入栈
while(!s.empty())
{
BiTree p=s.top();
s.pop(); //出栈
printf("%c",p->ch);
if(p->rchild) s.push(p->rchild); //右孩子入栈
if(p->lchild) s.push(p->lchild); //左孩子入栈
}
}
//方法二:这里采用深度遍历入栈,空结点也入栈
/*stack<BiTree> s; //初始化栈
s.push(T); //根结点入栈
while(!s.empty())
{
BiTree p=s.top(); //取栈顶元素
while(p)
{
printf("%c",p->ch);
s.push(p->lchild); //左孩子入栈
p=p->lchild; //p指向左孩子
}
s.pop(); //空结点出栈
if(!s.empty())
{
p=s.top(); //取栈顶元素
s.pop(); //出栈
s.push(p->rchild);//右孩子入栈
}
}*/
//方法三:这里采用深度遍历入栈的另外一种版本,空结点不入栈
/*stack<BiTree> s; //初始化栈
BiTree p=T; //初始化p
while(p||!s.empty())
{
if(p)
{
printf("%c",p->ch);
s.push(p); //入栈
p=p->lchild; //p指向左孩子
}
else
{
p=s.top(); //取栈顶元素
s.pop(); //出栈
p=p->rchild; //p指向右孩子
}
}*/
}
void InOrder(BiTree T){
//利用栈中序遍历二叉树非递归算法
//方法一:这里采用深度遍历入栈,空结点入栈
/*stack<BiTree> s; //初始化栈
s.push(T); //根结点入栈
while(!s.empty())
{
BiTree p=s.top();//取栈顶元素
while(p)
{
s.push(p->lchild);//左孩子入栈
p=s.top();//p=p->lchild//p指向左孩子
}
s.pop(); //空结点出栈
if(!s.empty())
{
p=s.top(); //取栈顶元素
s.pop(); //出栈
printf("%c",p->ch);
s.push(p->rchild);//右孩子入栈
}
}*/
//方法二:这里采用深度遍历入栈的另外一种版本,空结点不入栈
stack<BiTree> s; //初始化栈
BiTree p=T; //初始化p
while(p||!s.empty())
{
if(p)
{
s.push(p);//入栈
p=p->lchild;//p指向左孩子
}
else
{
p=s.top();//取栈顶元素
s.pop(); //出栈
printf("%c",p->ch);
p=p->rchild; //p指向右孩子
}
}
//方法三:这里采用广度遍历入栈
//tag=0,表示只有该结点入栈
//tag=1;表示该结点和左右孩子按中序入栈
/*stack<Mark_BiTree> s; //初始化栈
Mark_BiTree e; //定义标志二叉树
BiTree p=T; //初始化p
if(T){
e.ptr=p;
e.tag=0; //初始标志位:0
s.push(e); //根结点入栈
while(!s.empty())
{
e=s.top(); //获取栈顶元素
s.pop(); //出栈
p=e.ptr;
if(e.tag==0)//只有该结点入栈
{
if(p->rchild){
e.tag=0; //右孩子初始化
e.ptr=p->rchild;//右孩子入栈
s.push(e);
}
e.ptr=p; //重新设置标志位
e.tag=1; //表示该结点再次入栈,左右孩子也入栈
s.push(e);
if(p->lchild){
e.tag=0; //左孩子初始化
e.ptr=p->lchild;//左孩子入栈
s.push(e);
}
}
else{ //若该结点入栈,左右孩子也入栈,输出该结点值
printf("%c",e.ptr->ch);
}
}
}*/
}
void PostOrder(BiTree T){
//利用栈和标志位后序遍历二叉树非递归算法
//方法一:深度遍历入栈
//tag=0,表示该结点暂不处理,往左子树去
//tag=1;表示该结点可处理,从右子树回来
stack<Mark_BiTree> s; //初始化栈
BiTree p=T; //初始化p
Mark_BiTree e;//定义标志二叉树
while(p||!s.empty())
{
if(p)
{
e.tag=0;e.ptr=p;
s.push(e); //该结点暂不处理,入栈,往左子树去
p=p->lchild;
}
else
{
e=s.top();//获取栈顶元素
s.pop(); //出栈
int fag=e.tag; //获取标志位
p=e.ptr;
if(fag==0)
{
e.tag=1;//从左子树回来,往右子树去
s.push(e); //修改标志位,入栈
p=p->rchild;
}
else
{
printf("%c",p->ch);//从右子树回来,处理结点
p=NULL; //p置空,继续获取栈顶元素
}
}
}
//方法二:广度遍历入栈
//tag=0,表示只有该结点入栈
//tag=1;表示该结点和左右孩子按后序入栈
/*stack<Mark_BiTree> s; //初始化栈
Mark_BiTree e; //定义标志二叉树
BiTree p=T; //初始化p
if(T){
e.ptr=p;
e.tag=0; //初始标志位:0
s.push(e); //根结点入栈
while(!s.empty())
{
e=s.top(); //获取栈顶元素
p=e.ptr;
if(e.tag==0)//只有该结点入栈
{
s.top().tag=1;//重新设置标志位,表示左右孩子也入栈
if(p->rchild){
e.tag=0; //右孩子初始化
e.ptr=p->rchild;//右孩子入栈
s.push(e);
}
if(p->lchild){
e.tag=0;//左孩子初始化
e.ptr=p->lchild;//左孩子入栈
s.push(e);
}
}
else{ //若该结点入栈,左右孩子也入栈,输出该结点值
printf("%c",e.ptr->ch);
s.pop(); //该结点出栈
}
}
}*/
//方法三:方法一的另一种版本,采用深度遍历入栈
//为了区分两次过栈的不同处理方式,在二叉树中增加一个标志位,tag=0表示刚刚访问此结点,
//tag=1表示处理了左子树,从左子树回来,tag=2表示处理了右子树,
//从右子树回来.每次根据栈顶元素的tag值决定做何种动作.
/*if(T)
{
Mark_BiTree e; //定义标志二叉树
stack<Mark_BiTree> s; //初始化栈
BiTree p=T; //初始化p
e.ptr=T;
e.tag=0; //标志位初始化
s.push(e); //根结点入栈
while(!s.empty())
{
e=s.top(); //获取栈顶元素
p=e.ptr;
s.pop(); //出栈
switch(e.tag)//根据标志位,选择不同处理方式
{
case 0: //该结点刚入栈
e.tag=1; //修改标志位
e.ptr=p;
s.push(e); //该结点再次入栈
if(e.ptr->lchild)
{
e.ptr=e.ptr->lchild;
e.tag=0; //左子树初始化
s.push(e);//左子树入栈
}
break;
case 1: //从左子树回来,开始处理右子树
e.tag=2; //修改标志位
e.ptr=p;
s.push(e); //该结点再次入栈
if(e.ptr->rchild)
{
e.ptr=e.ptr->rchild;
e.tag=0;//右子树初始化
s.push(e);//右子树入栈
}
break;
case 2:
printf("%c",p->ch);//从右子树回来,可以处理该结点
}
}
}*/
}
void LayerOrder(BiTree T){
//利用队列层序遍历二叉树非递归算法
queue<BiTree> q; //初始化队列
if(T){
q.push(T); //入队
while(!q.empty())
{
BiTree p=q.front();//获取队首元素
q.pop(); //出队
printf("%c",p->ch);
if(p->lchild) q.push(p->lchild);//左孩子入队
if(p->rchild) q.push(p->rchild);//右孩子入队
}
}
}
int main(){
BiTree T;
CreateBiTree(T); //创建二叉树
printf("先序遍历结果:");
PreOrder(T);
printf("/n");
printf("中序遍历结果:");
InOrder(T);
printf("/n");
printf("后序遍历结果:");
PostOrder(T);
printf("/n");
printf("层序遍历结果:");
LayerOrder(T);
printf("/n");
return 0;
}
例子三:Kruskal并查集实现最小生成树
#define MAX 100
#include <iostream>
using namespace std;
struct edge
{
int cost;
int first;
int second;
};
int set[MAX];
edge my_pair[MAX];
int rank[MAX];
int FindSet(int x)
{
if(set[x]!=x)
set[x]=FindSet(set[x]);
return set[x];
}
void MakeSet(int n)
{
for(int i=1;i<=n;i++){
set[i]=i;rank[i]=0;
}
}
void Link(int a,int b)
{
if(rank[a]>rank[b])
set[b]=a;
else if(rank[a]<rank[b])
set[a]=b;
else
{
set[a]=b;
rank[b]++;
}
}
void Union(int a,int b)
{
Link(FindSet(a),FindSet(b));
}
int my_cmp(const void* a,const void* b)
{
return (*(edge*)a).cost-(*(edge*)b).cost;
}
int main()
{
int N,M,lowcost(0),i,count(1);
scanf("%d%d",&N,&M);
MakeSet(N);
for(i=0;i<M;i++)
{
scanf("%d%d%d",&my_pair[i].first,&my_pair[i].second,&my_pair[i].cost);
}
qsort(my_pair,M,sizeof(edge),my_cmp);
for(i=0;i<M&&count<N;i++)
{
int first_root=FindSet(my_pair[i].first);
int second_root=FindSet(my_pair[i].second);
if(first_root!=second_root)
{
Union(first_root,second_root);
printf("%d----%d/n",my_pair[i].first,my_pair[i].second);
lowcost+=my_pair[i].cost;
count++;
}
}
printf("%d/n",lowcost);
return 0;
}
例子四:二叉排序树
#include <iostream>
using namespace std;
struct BiTree{
int data;
struct BiTree *lchild,*rchild;
};
BiTree *T;
void CreateOrderBiTree(int x)
{
BiTree *node=new BiTree;
node->data=x;
node->lchild=node->rchild=NULL;
if(!T) T=node;
else
{
BiTree *back;
BiTree *cur=T;
while(cur)
{
back=cur;
if(cur->data>x)
cur=cur->lchild;
else cur=cur->rchild;
}
if(back->data>x)
back->lchild=node;
else back->rchild=node;
}
}
void InOrder(BiTree *bt)
{
if(bt)
{
InOrder(bt->lchild);
cout<<bt->data<<" ";
InOrder(bt->rchild);
}
}
int main(){
T=NULL;
int n,i,a;
cin>>n;
for(i=0;i<n;i++)
{
cin>>a;
CreateOrderBiTree(a);
}
InOrder(T);
cout<<endl;
return 0;
}
例子四:二叉树操作汇集
#include<iostream>
#include<stack>
using namespace std;
typedef struct node
{
char ch;
struct node *lchild,*rchild;
int nodecount;
}BiTNode,*BiTree;
void PreOrder(BiTree T){
//先序递归遍历二叉树
if(T){
printf("%c",T->ch);
if(T->lchild) PreOrder(T->lchild);
if(T->rchild) PreOrder(T->rchild);
}
}
void PostOrder(BiTree T){ //后序递归遍历二叉树
if(T){
PostOrder(T->lchild);
PostOrder(T->rchild);
printf("%c:%d ",T->ch,T->nodecount);
}
}
void CreateBiTree(BiTree &T){
//创建二叉树
char ch;
scanf("%c",&ch);
if(ch=='#') T=NULL;
else{
T=new BiTNode;
T->ch=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
}
void CountLeaf(BiTree T,int &Count){
//统计二叉树叶子结点的个数
if(T){
if((!T->lchild)&&(!T->rchild))
Count++;
CountLeaf(T->lchild,Count);
CountLeaf(T->rchild,Count);
}
}
int Leaf_Count(BiTree T)//求二叉树中叶子结点的数目
{
//统计二叉树叶子结点的个数另一种版本
if(!T) return 0; //空树没有叶子
else if(!T->lchild&&!T->rchild) return 1; //叶子结点
else{
int m=Leaf_Count(T->lchild);
int n=Leaf_Count(T->rchild);
return (m+n);
//return Leaf_Count(T->lchild)+Leaf_Count(T->rchild);//左子树的叶子数加上右子树的叶子数
}
}
void BiTreeDepth(BiTree T,int level,int &depth){
//求二叉树的深度
//level为T所指结点所在层次,初值为1,
//depth为当前求得的最大层次,初值为0.
if(T)
{
if(level>depth) depth=level;
BiTreeDepth(T->lchild,level+1,depth);
BiTreeDepth(T->rchild,level+1,depth);
}
}
int DepthOfBiTree(BiTree T){
//求二叉树深度的另一种版本
if(!T) return 0;
else
{
int m=DepthOfBiTree(T->lchild);
int n=DepthOfBiTree(T->rchild);
//if(m>n) return (m+1);
//else return (n+1);
return (m>n?m:n)+1;
}
}
void Depth_BiTree(BiTree T,int &depth){
//求二叉树深度的第三种版本
if(!T) depth=0;
else
{
int m,n;
Depth_BiTree(T->lchild,m);
Depth_BiTree(T->rchild,n);
depth=(m>n?m:n)+1;
}
}
BiTNode *GetTreeNode(char ch,BiTree lptr,BiTree rptr){
//生成一个元素值为ch,左指针为lptr,右指针为rptr的结点
BiTree T=new BiTNode;
T->ch=ch;
T->lchild=lptr;
T->rchild=rptr;
return T;
}
BiTNode *CopyTree(BiTree T){
//已知二叉树的根指针,返回复制后的根指针
BiTree newlptr,newrptr;
if(!T) return NULL;
if(T->lchild)
newlptr=CopyTree(T->lchild);
else newlptr=NULL;
if(T->rchild)
newrptr=CopyTree(T->rchild);
else newrptr=NULL;
BiTree newnode=GetTreeNode(T->ch,newlptr,newrptr);
return newnode;
}
void BiTree_Copy(BiTree T,BiTree &U)
{
//非递归复制二叉树,有错误
stack<BiTree> s1,s2;
s1.push(T); //根指针进栈
BiTree q=U,p;
while(!s1.empty())
{
p=s1.top();
q=s2.top();
while(p)
{
q=new BiTNode;
q->ch=p->ch;
s1.push(p->lchild);
p=p->lchild;
q=q->lchild;
s2.push(q);
}//向左走到尽头
s1.pop();
s2.top()=NULL;
s2.pop();
if(!s1.empty())
{
p=s1.top();
s1.pop();
s1.push(p->rchild);//向右一步
q=s2.top();
s2.pop();
q=q->rchild;
}
}
}
void eularTour(BiTree T,int &Count)//欧拉路径遍历
{
//统计每个结点后代的数目
int temp=Count;
if(T->lchild) eularTour(T->lchild,++Count);
if(T->rchild) eularTour(T->rchild,++Count);
printf("%c:%d ",T->ch,Count-temp);
}
int NodeCount(BiTree T)
{
//统计每个结点后代的数目的另一种方法
if(!T) return 0;
return (T->nodecount=NodeCount(T->lchild)+NodeCount(T->rchild))+1;
}
int CountNode(BiTree T){
//统计二叉树中所有结点的数目
if(!T) return 0;
if(!T->lchild&&!T->rchild) return 1;
else
{
int m=CountNode(T->lchild);
int n=CountNode(T->rchild);
return (m+n+1);
//return CountNode(T->lchild)+CountNode(T->rchild)+1;
}
}
void Count_Node(BiTree T,int &num){
//统计二叉树中所有结点的数目的另一种版本
if(T)
{
num++;
Count_Node(T->lchild,num);
Count_Node(T->rchild,num);
}
}
int main(){
BiTree T;
CreateBiTree(T);
printf("二叉树所有结点的个数:%d/n",CountNode(T));
int num=0;
Count_Node(T,num);
printf("二叉树所有结点的个数的另一种版本:%d/n",num);
int Count=0;
CountLeaf(T,Count);
printf("二叉树叶子结点的个数:%d/n",Count);
printf("二叉树叶子结点的个数的另一种版本:%d/n",Leaf_Count(T));
int depth=0;
BiTreeDepth(T,1,depth);
printf("二叉树的深度为:%d/n",depth);
printf("二叉树深度的另一种版本:%d/n",DepthOfBiTree(T));
depth=0;
Depth_BiTree(T,depth);
printf("二叉树深度的另一种版本:%d/n",depth);
BiTree bt=CopyTree(T);
printf("递归复制过后的二叉树:");
PreOrder(bt);
printf("/n");
//BiTree U;//有错误
//BiTree_Copy(T,U);
//printf("非递归复制过后的二叉树:");
//PreOrder(U);
//printf("/n");
printf("二叉树每个结点后代的数目:");
int nodecount=0;
eularTour(T,nodecount);
printf("/n");
printf("二叉树每个结点后代的数目的另一种方法:");
NodeCount(T);
PostOrder(T);
printf("/n");
return 0;
}
四:图和图的遍历
例子一:邻接表表示图的深度遍历和广度遍历
#define MAX_VERTEX_NUM 20 //顶点个数
#include<iostream>
#include<string>
#include<queue> //队列头文件
using namespace std;
typedef int AdjType;
typedef string VexType;
bool visited[MAX_VERTEX_NUM]; //标记是否采访过
typedef struct ArcNode //采用邻接表作为存储结构,实现无向图的遍历
{
AdjType adj;
struct ArcNode *nextarc;
}ArcNode;
typedef struct VertexNode
{
VexType data;
ArcNode *firstarc;
}AdjList;
typedef struct ALGraph
{
AdjList vertex[MAX_VERTEX_NUM];
int vexnum,arcnum;
}ALGraph;
void Insert_ArcNode(int i,int j,ALGraph &G)//插入某一条边
{
ArcNode *p=new ArcNode;
p->adj=j;
//p->nextarc=G.vertex[i].firstarc;//采用头插入法
//G.vertex[i].firstarc=p;
ArcNode *q=G.vertex[i].firstarc;//按顺序插入
if(!q||j<q->adj)//若为空值或者即将插入的结点序号小于首结点的序号
{
p->nextarc=q;//插入首结点之前
G.vertex[i].firstarc=p;
}
else
{
while(q->nextarc&&j>q->nextarc->adj)//寻找插入位置
q=q->nextarc;
p->nextarc=q->nextarc;//插入该结点之前
q->nextarc=p;
}
}
void Init_ALGraph(ALGraph &G)//初始化图
{
int i,j,k;
printf("请输入图的顶点数:");
cin>>G.vexnum;
printf("请输入图的边数:");
cin>>G.arcnum;
printf("请输入顶点的数值:");
for(k=0;k<G.vexnum;k++)
cin>>G.vertex[k].data;
for(k=0;k<G.arcnum;k++)
G.vertex[k].firstarc=NULL;//置空值
printf("请输入相关联的边:/n");
for(k=0;k<G.arcnum;k++)
{
cin>>i>>j;
Insert_ArcNode(i-1,j-1,G);//插入该边
Insert_ArcNode(j-1,i-1,G);
}
}
void DFS(ALGraph G,int i)//深入优先搜索
{
visited[i]=true;
cout<<G.vertex[i].data<<" ";
ArcNode *p=G.vertex[i].firstarc;
while(p)
{
i=p->adj;
if(!visited[i])
DFS(G,i);
p=p->nextarc;
}
}
void DFSTraverse(ALGraph G)
{
memset(visited,false,sizeof(visited));//赋初值
for(int i=0;i<G.vexnum;i++)
if(!visited[i])//遍历各个顶点
DFS(G,i);
}
void BFS(ALGraph G,int i)//宽度优先搜索
{
queue<int> q;//初始化队列
q.push(i);
visited[i]=true;//采访过
cout<<G.vertex[i].data<<" ";//输出
while(!q.empty())
{
i=q.front();
q.pop();
ArcNode *p=G.vertex[i].firstarc;
while(p)
{
i=p->adj;
if(!visited[i])
{
q.push(i);
visited[i]=true;
cout<<G.vertex[i].data<<" ";
}
p=p->nextarc;
}
}
}
void BFSTraverse(ALGraph G)
{
memset(visited,false,sizeof(visited));
for(int i=0;i<G.vexnum;i++)
if(!visited[i])
BFS(G,i);
}
int main()
{
ALGraph G;
Init_ALGraph(G);
printf("深度优先遍历结果:/n");
DFSTraverse(G);
printf("/n");
printf("广度优先遍历结果:/n");
BFSTraverse(G);
printf("/n");
return 0;
}
例子二:邻接矩阵表示图的深度遍历和广度遍历
#define MAX_VERTEX_NUM 20 //顶点个数
#include<iostream>
#include<string>
#include<queue> //队列头文件
using namespace std;
typedef int AdjMatrix;
typedef string VexType;
bool visited[MAX_VERTEX_NUM]; //标记是否采访过
typedef struct MGraph //采用邻接矩阵作为图的存储结构
{
VexType vertex[MAX_VERTEX_NUM];
AdjMatrix arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int vexnum,arcnum;
}MGraph;
void Init_MGraph(MGraph &G)//初始化图
{
int i,j,k;
printf("请输入图的顶点数:");
cin>>G.vexnum;
printf("请输入图的边数:");
cin>>G.arcnum;
printf("请输入顶点的数值:");
for(k=0;k<G.vexnum;k++)
cin>>G.vertex[k];
for(i=0;i<G.vexnum;i++)
for(j=0;j<G.vexnum;j++)
G.arcs[i][j]=0; //初始化邻接矩阵
printf("请输入相关联的边:/n");
for(k=0;k<G.arcnum;k++)
{
cin>>i>>j;
G.arcs[i-1][j-1]=1; //插入该边
G.arcs[j-1][i-1]=1;
}
}
void DFS(MGraph G,int i)//深入优先搜索
{
visited[i]=true;//采访过
cout<<G.vertex[i]<<" "; //输出
for(int j=0;j<G.vexnum;j++)//遍历相关联的边
if(G.arcs[i][j]&&!visited[j])
DFS(G,j);
}
void DFSTraverse(MGraph G)
{
memset(visited,false,sizeof(visited));//赋初值
for(int i=0;i<G.vexnum;i++)
if(!visited[i])//遍历各个顶点
DFS(G,i);
}
void BFS(MGraph G,int i)//宽度优先搜索
{
queue<int> q; //初始化队列
q.push(i); //进队列
visited[i]=true; //采访过
cout<<G.vertex[i]<<" "; //输出
while(!q.empty())
{
i=q.front();
q.pop();
for(int j=0;j<G.vexnum;j++)//遍历相关联的边
if(G.arcs[i][j]&&!visited[j])
{
q.push(j); //进队列
visited[j]=true;//采访过
cout<<G.vertex[j]<<" ";//输出
}
}
}
void BFSTraverse(MGraph G)
{
memset(visited,false,sizeof(visited));//赋初值
for(int i=0;i<G.vexnum;i++)//遍历各个顶点
if(!visited[i])
BFS(G,i);
}
int main()
{
MGraph G;
Init_MGraph(G);
printf("深度优先遍历结果:/n");
DFSTraverse(G);
printf("/n");
printf("广度优先遍历结果:/n");
BFSTraverse(G);
printf("/n");
return 0;
}
备注:算法应该不会考,排序,查找也应该不会考。查找算法例子如下:
例子一:创建顺序表的二分查找(折半查找),返回查找值的位置
#include<iostream>
using namespace std;
int cmp(const void*b,const void*c){
return *(int*)b-*(int*)c;
}
int binsearch(int *p,int elem,int n){
int low=0,high=n-1,mid;
while(low<=high){
mid=(low+high)/2;
if(p[mid]==elem)
return mid+1;
else if(p[mid]>elem)
high=mid-1;
else
low=mid+1;//返回查找元素的位置
}
return -1;
}
int main(){
int n,i;
cin>>n;
int *p=new int[n];
for(i=0;i<=n-1;++i)
cin>>p[i];
qsort(p,n,sizeof(int),cmp);
for(i=0;i<=n-1;++i)
cout<<p[i]<<" ";
cout<<endl;
cout<<binsearch(p,6,n)<<endl;
return 0;
}
例子二:顺序表的二分查找(折半查找),即bsearch() 的应用
#include<iostream>
using namespace std;
int cmp(const void*b,const void*c){
return *(int*)b-*(int*)c;
}
int main(){
int n,i;
cin>>n;
int *p=new int[n];
for(i=0;i<=n-1;++i)
cin>>p[i];
qsort(p,n,sizeof(int),cmp);
for(i=0;i<=n-1;++i)
cout<<p[i]<<" ";
cout<<endl;
int e;
cin>>e;
int *q,*t=&e;
q=(int*)bsearch(t,p,n,sizeof(int),cmp);
cout<<*q<<endl;
return 0;
}