1.排序部分
1、直接插入排序
void InsertSort(ElemType A[],int n)
{
int i,j;
for(i=2;i<=n;i++)
{
if(A[i-1]>A[i])
{
A[0]=A[i];
for(j=i-1;A[j]>A[0];j--)
{
A[j+1]=A[j];
}
A[j+1]=A[0];
}
}
}
2、二分插入排序
void InsertSort(ElemType A[],int n)
{
int i,j,low,mid,high;
for(i=2;i<=n;i++)
{
low=1;high=i-1;A[0]=A[i];
while(low<=high)
{
mid=(low+high)/2;
if(A[0]<A[mid])high=mid-1;
else low=mid+1;
}
for(j=i-1;j>high;j--)A[j+1]=A[j];
A[high+1]=A[0];
}
}
3、希尔排序
void ShellSort(ElemType A[],int n)
{
int i,j,dk;
for(dk=n/2;dk>=1;dk/=2)
{
for(i=dk+1;i<=n;i++)
{
if(A[i-dk]>A[i])
{
A[0]=A[i];
for(j=i-dk;j>0&&A[j]>A[0];j-=dk)
A[j+dk]=A[j];
A[j+dk]=A[0];
}
}
}
}
4、冒泡排序
void BubbleSort(ElemType A[] , int n)
{
for(i=0;i<n-1;i++)
{
flag=false;
for (j=n-1; j>i ; j--)
{
if(A[j-1]>A[j])
{
swap (A [ j - 1] , A [ j ]) ;
flag=true;
}
}
if (flag==false)
return;
}
}
5、快速排序
void QuickSort(int A[],int low,int high)
{
while(low<high)
{
int povitpos=Partition(A,low,high);
QuickSort(A,low,povitpos-1);
QuickSort(A,povitpos+1,high);
}
}
int Partition(int A[],int low,int high)
{
int povit=A[low];
while(low<high)
{
while(low<high&&A[high]>=povit)
high--;
A[low]=A[high];
while(low<high&&A[low]<=povit)
low++;
A[high]=A[low];
}
A[low]=povit;
return low;
}
6、简单选择排序
①数组
void SelectSort(int A[],int n)
{
int i,j,min;
for(i=1;i<n;i++)
{
min=i;
for(j=i+1;j<=n;j++)
{
if(A[j]<A[min])min=j;
}
if(min!=i)
{
A[0]=A[i];A[i]=A[min];A[min]=A[0];
}
}
}
②有头链表
void Selectsort(Node *Head)
{
Node *now,*temp,*min;
now = Head;
for (; now != NULL;now=now->next)
{
temp = now->next;
min = temp;
while (temp != NULL)
{
//找到最小值节点
if (temp->data < min->data)
{
min = temp;
}
temp = temp->next;
}
for (temp = now->next; temp->next != min; temp = temp->next);
//找到最小值节点前一个节点
temp->next = min->next;
//取出最小节点
min->next = now->next;
now->next = min;
}
}
7、堆排序
void BuildMaxHeap(int A[],int len)
{
for(int i=len/2;i>=1;i--)AdjustDown(A,i,len);
}
void AdjustDown(int A[],int k,int len)
{
A[0]=A[k];
for(int i=2*k;i<=len;i*=2)
{
if(i<len&&A[i]<A[i+1])i++;
if(A[0]>=A[i])break;
else
{
A[k]=A[i];
k=i;
}
}
A[k]=A[0];
}
void HeapSort(int A[],int len)
{
Build(A,len);
for(int i=len;i>=1;i--)
{
A[0]=A[i];A[i]=A[1];A[1]=A[0];
AdjustDown(A,1,i-1);
}
}
8、归并排序
void Merge(int A[],int low,int mid,int high)
{
int B[]=new int[n+1];
int i,j,k;
for(i=1;i<=n;i++)B[i]=A[i];
for(i=low,j=mid+1,k=1;i<=mid&&j<=high;k++)
{
if(B[i]<B[j])A[k]=B[i++];
else A[k]=B[j++];
}
while(i<=mid)A[k++]=B[i++];
while(j<=high)A[k++]=B[j++];
}
void MergeSort(int A[],int low,int high)
{
while(low<high)
{
int mid=(low+high)/2;
MergeSort(A,low,mid);
MergeSort(A,mid+1,high);
Merge(A,low,mid,high);
}
}
2.链表部分
1、在一个递增有序的线性表中,有数值相同的元素存在,若存储方式为单链表,设计算法去除数值相同的元素,使表中不再有重复的元素。
void Del_Same(LinkList &L)
{
//L是递增有序的单链衰,本算法删除表中数值相同的元素
LNode *p=L->next ,*q;
if (p==NULL)
return ;
while (p - >next ! =NULL)
{
q=p- >next ;
if (p->data==q- >data )
{
p - >next=q- >next;
free (q);
}
else
p=p->next ;
}
}
2、已知一无表头结点的单链表 ,结点结构为(data,next) 以 H 为头指针, 每个结点的 data 域存放的是一个自然数, 设计一个算法, 能统计出该链表中偶数的个数。
int count (LinkList L)
{
p=L; count1=0;
while(p)
{
if (p->data%2==0) count1++;
p=p->next;
}
return count1;
}
3、设在一个带头结点的双向链表中,所有结点的数据元素按值递增顺序排列,写一算法,删除表中所有大于min,小于max的元素(若存在)。双链表的定义如下:
typedef struct DLnode
{
int data;
DLnode *pre, *next;
}DLnode;
Status delnode(DuLinklist &la ,int mink, int maxk)
{//有头结点
if (la->next= =NULL) return ERROR;
if (mink>maxk) return ERROR;
q=la; p=la->next;
while(p&&p->data<=mink)
{
q=p;p=p->next;
}
while(p&&p->data<maxk)
{
s=p;p=p->next;free(s);
}
q->next=p;p->pre=q;
return ok;
}
4、设在n个数据存在一维数组r中,试写一个算法将数据按原始顺序构造一个带有头结点的双向循环链表。
函数名为: Convert(r,la,n),其中r为存有n个数据的一维数组,la为链表头指针。 双向链表的三个域为:数据域data,前向指针prior,后向指针next,数组下标从0计。
void Convert(r,la,n)
{
q=la=new DlNode;
la->prior=q->next=la;
for(i=0;i<n;i++)
{
p=new DlNode;
p->data=r[i];
p->prior=q;
p->next=q->next;
q->next=p;
q=p;
}
la->prior=p;
}
5、已知一个如下图所示的带头结点的单链表 head(注:若头指针名是 head,则把单链表称为表 head),其存储结构为:
Typedef struct Node
{
Elemtype data; struct lnode *next;
}lnode,*linklist;
删除表中值最大的结点。
void DeleteMaxNode(Linklist &L)
{
LNode *pre=L,*p=pre->next;
LNode *maxpre=pre,*maxp=p;
while(p!=NULL)
{
if(p->data>maxp->data)
{
maxp=p;
maxpre=pre;
}
pre=p;
p=p->next;
}
maxpre->next=maxp->next;
free(maxp);
}
6、有带头结点的递增有序单链表heada和headb,存储的分别为数据集A和B,要求完成求差集A-B的算法void difference(heada,headb,n)(即完成从A的链表中删除B链表中数据的工作),同时返回最后A集合的元素个数n。
void Difference(LinkList A, LinkList,B, int &n)
{ //n是结果集合中元素的个数,调用时为0
p = A->next; //链表A的工作指针
q = B->next; //链表B的工作指针
pre = A; //pre为A中p所指结点的前驱结点的指针
while (p!=NULL && q!=NULL)
{
if (p->data < q->data)
{
//A链表中当前结点指针后移
pre = p;
p = p->next;
n++;
}
else if (p->data > q->data) //B链表中当前结点指针后移
q = q->next;
else
{
//处理A,B中元素值相同的结点,应删除
pre->next = p->next;
u = p;
p = p->next;
free(u);
}
}
}
7、统计出单链表L中结点的值大于给定值a的结点数。
int CountA(LNode* L, ElemType a)
Int countA(Lnode *L,ElemType a)
{
Londe *p=L;
Int sum=0;
While(p)
{
If(p->data>a)
{
Sum++;
}
}
Return sum;
}
8、已知一个带头结点的按值非递减的单循环链表,节点类型为(data,next)。以head为头指针,每个节点的data域存放的是一个整数,试构造一个删除所有值大于min小于max的结点的算法。函数原型为void rangdelete(Lnode &head,int min,int max)。
Void range(Londe *&head,int min,int max)
{
Lnode *pr=head,*p=head->next;
While(p!=head&&p->data<=min)
{
Pr=p;
P=p->next;
}
While(p!=head&&p->data<max)
{
Pr->next=p->next;
Delect p;
P=pr->next;
}
}
9、已知一个带头结点单链表中,节点类型为(data,next)。构造一个算法,在链表中第一个值为x的数据后插入值为y的结点,若该节点不存在,则在链表的最后插入y结点。函数原型为void insertxy(Node &head,int x,int y)。
void insertxy(Node &head,int x,int y)
{
Node *p=head;
While(p)
{
If(p->data==x)
{
Node new;
new->data=y;
new->next=p->next;
p->next=new;
break;
}
p=p->next;
}
if(p->next==NULL)
{
Node new;
new->data=y;
new->next=p->next;
p->next=new;
}
}
10、设有线性表L={a1,a2,…,an},顺序存储,试写一个算法将该线性表的元索按原始顺序构造一个有头结点的单链表。
status Convert(sqList L,LinkList &La)
顺序表的存储结构为:
typedef struct
{
ElemType *elem;
int length;
int listsize;
} SqList;
单链表的存储结构定义为:
typedef struct LNode
{
ElemType data;
struct LNode *next;
}LNode, *LinkList;
Status Convert(SqList L,LinkList&La)
{
LinkList *s,*r;
int i;
La=(LinkList*)malloc(sizeof(LinkList));
r=La;
for(i=0;i<L.length;i++)
{
s=(LinkList*)malloc(sizeof(LinkList));
s->data=*(L.elem+i);//按照顺序为新的结点赋值
r->next=s;//连接到La链表后
r=s;//更新指针
}
r->next=null;
}
11、编写一个算法来交换单链表中指针 P所指结点与其后继结点,Head 是该链表的头指针,P指向该链表中某一结点。
typedef struct Node
{
int data;
Node *next;
}Node;
void Swap(Node *p, Node *Head)
{
Node *before, *after;
before = Head;
while (before->next!=p&&before != NULL)
{
//寻找结点P
before = before->next;
}
//交换结点p与其后一个结点
after = p->next;
p->next = after->next;
after->next = p;
before->next = after;
}
12、有一个整数元素建立的单链表A,如下算法实现将其拆分成两个单链表A和B,使得A单链表中含有所有的偶数结点,B单链表中所有的奇数结点,且保持原来的相对次序。阅读该算法并将空格处补充完整。
typedef int ElemType;
typedef struct node
{
ElemType data;
struct node *next;
}SLink;
void Split(SLink *&A. SLink *&B)
{
SLink *p=A->next, *ra,*rb;
ra=A;
B=(SLink *)malloc(sizcof(SLink);
rb=B;
while(p!=null)
{
if(p->data%2==0)
{
ra->next=p;
ra=p;
p=p->next;
}
else
{
rb->next=p;
rb=p;
p=p->next;
}
}
ra->next=rb->next=NULL;
}
13、链表带头节点的head单链表,设计算法返回中间节点的地址
SListNode * FindMidNode(SListNode * phead)
//设一个fast结点和一个slow结点,fast每次后移两个结点,slow每次后移一个结点,当fast移//动完成,slow结点恰好指向中间结点。
{
SListNode *fast = phead;
SListNode *slow = phead;
while (fast)
{
if (fast->next != NULL)
{
fast = fast->next->next;
}
else
{
break;
}
slow = slow->next;
}
return slow;
}
14、有两个有序链表A、B,计算A∩B(不能有重复数据),结果保留在链表A中,并计算最后链表A中的结点的个数,函数名为 int count(LinkList &la,LinkList &lb)。
int count(LinkList &la,LinkList &lb)
{
int num=0;
pa=la->next;
pb=lb->next;
pc=la; //结果表中当前合并节点的前驱指针
while(pa&pb)
{
if(pa->data==pb->data)
{ //交集并入结果表中
pc->next=pa;//A中结点链接到结果表
pc=pa;
pa=pa->next;
u=pb;
pb=pb->next;
free(u);
num++;
}
else if(pa->data<pb->data)
{
//若A中当前结点值小于B中当前结点值,A指针后移
u=pa;
pa=pa->next;
free(u);
}
else
{
//若B中当前结点值小于A中当前结点值,B指针后移
u=pb;
pb=pb->next;
free(u);
}
}
while(pa)
{
//B已经遍历完,A没有遍历完
u=pa;
pa=pa->next;
free(u);
}
while(pb)
{
//A已经遍历完,B没有遍历完
u=pb;
pb=pb->next;
free(u);
}
pc->next=NULL;//结果链表尾指针置空
free(lb);//释放B表的头结点
return num;
}
15、判断单链表中的元素是否递增
int isriselk(lklist *head)
{
if (head==0||head->next==0) return 1;
else
{
for(q=head,p=head->next; p!=0; q=p,p=p->next)
if(q->data>p->data)
return 0;
}
return 1;
}
16、判断单链表中结点是否关于中心对称
typedef struct
{
int s[100];
int top;
} sqstack;
int lklistsymmetry(lklist *head)
{
sqstack stack;
stack.top= -1;
lklist *p;
for(p=head;p!=0;p=p->next)
{
stack.top++;
stack.s[stack.top]=p->data;
}
for(p=head;p!=0;p=p->next)
{
if (p->data==stack.s[stack.top])
stack.top=stack.top-l;
else return 0;
}
return 1;
}
17、判断一个带表头结点的双向循环链表 DL(DuLinkList)是否对称。(比如,表(25,34,34,25)和表(25,3,25)为对称的)。
typedef struct dnode //定义双链表结点的数据结构
{
int data;
struct dnode *lnext;
struct dnode *rnext;
}Dnode;
bool issymmetry17(Dnode *h)
{
Dnode *lnode = h->lnext;
Dnode *rnode = h->rnext;
while (!(lnode == rnode || lnode->lnext == rnode))
{
if (lnode->data != rnode->data)
return false;
lnode = lnode->lnext;
rnode = rnode->rnext;
}
return true;
}
3.树部分
- 先序递归
void preorder(p)
{
if(p!=NULL)
{
cout<<p->data;
preorder(p->lchild);
preorder(p->rchild);
}
}
- 中序递归
void inorder(p)
{
if (p)
{ inorder (p->lchild);
cout<<p->data; inorder (p->rchild);
}
}
- 后序递归
void postorder(p)
{
if (p)
{ postorder(p->lchild); postorder (p->rchild);
cout<<p->data;
}
}
- 叶子计数
int count(p)
{
if(p)
{
m=count(p->lchild);
m+=count(p->rchild);
if( !m ) return 1;
else return m;
}
else return 0;
}
- 二叉树拷贝
void CopyTree(t,s) //源s 目的t
{
if(s)
{
t=new TreeNode;
t->data=s->data;
CopyTree(t->lchild,s->lchild);
CopyTree(t->rchild,s->rchild);
}
else t=NULL;
}
- 中序非递归
void inorder(t)
{
InitStack(S);
p=t;
while(p!=NULL || !(IsEmpty(S))
{
if(p)
{
Push(S,p);
p=p->lchild;
}
else
{
Pop(S,p);
cout<<p->data;
p=p->rchild;
}
}
}
7、二叉树左右子树交换的递归算法
void Bitree_Revolute(Bitree T)
{
if(T)
{
T->lchild<->T->rchild;
Bitree_Revolute(T->lchild);
Bitree_Revolute(T->rchild);
}
}
8、完成一个在根为tree的二叉排序树中插入数据x的算法insert (tree,x)。(二叉排序树结点的三个域为:左、右孩子lchild与rchild,数据域dada)
void insert (tree,x)
{
if(tree!=NULL)
{
if(x<tree->data)
insert (tree->lchild,x);
else
insert (tree->rchild,x);
}
else
{
tree=new TreeNode;
tree->lchild=tree->rchild=NULL;
tree->data=x;
}
}
9、总结点数
int nodeNum(BiTree T)
{
if(T == NULL) return 0;
if(T->lchild == NULL && T->rchild == NULL) return 1;
return nodeNum(T->lchild) + nodeNum(T->rchild) + 1;
}
10、递归完成一个求二叉树结点数的算法 int CountNode(p),结点数由函数返回,p 是二叉树的根。
int CountNode(P)
{
if(P)
return CountNode(P->lchild )+ CountNode(P->rchild )+1;
else
return 0;
}
11、二叉树采用二叉链表作为存储结构,链表中的节点结构为:
typedef struct bitNode
{
int data;
bitnode *lt;
bitnode *rt;
}bitNode;
构造一个计算二叉树中度为2且节点的值小于x的结点个数的递归算法。函数原型为int countx(bitNode *t,int x)。
Int countx(bitnode *t,int x)
{
If(t)
{
if(t->lt&&t->rt&&t->data<x)
return 1+countx(t->lt,x)+countx(t->rt);
else
return countx(t->lt,x)+countx(t->rt);
}
else return 0;
}
12、试设计判断两棵二叉树是否相似的算法,所谓二叉树T1和T2 相似,指的是T1和T2都是空的二叉树或都只有一个根结点;或T1的左子树和T2的左子树是相似的,且T1的右子树和T2的右子树是相似的。
int similar (BiTree T1,BiTree T2)
{
int leftS, rightS ;
if (T1==NULL&&T2==NULL)
return 1;
else if (T1==NULL||T2==NULL)
return 0;
else
{
leftS=similar(T1->lchild,T2->lchild);
rightS=similar(T1->rchild,T2->rchild);
return leftS&&rightS;
}
}
13、递归实现从大到小输出二叉排序树中所有其值不小于k的关键字。
typedef int KeyType;
typedef char ElemType;
typedef struct tnode
{
KeyType key;
ElemType data;
struct tnode *lchild,*rchild;
}BSTNode;
void Output(BSTNode *bt,KeyType k)
{
if(bt!=NULL)
{
Output(bt->rchild,k);
if(bt->key>=k)
print(“%d,bt->key”);
Output(bt->lchild,k);
}
}
14、二叉树采用二叉链表作为存储结构,链表中结点的左、右孩子域为lchild、 rchild。请编写一个算法,计算二叉树中叶子结点按从左到右的顺序构成单链表,链表利用叶子结点的 rchild 链接,链表头指针为h_tree,(tree为二叉树根结点指针) void Linkleaf(tree,h_tree)。
typedef struct tree
{
int data;
struct tree *left;
struct tree *right;
}node, *pnode;
pnode firstLeaf; // 记录叶子链表的第一个叶子结点
pnode pcur; // 记录叶子链表的当前结点
void leafLink(pnode root)
{
if(!root) {return;}
if(NULL == root->left && NULL == root->right)
{
if(NULL == firstLeaf)
{
firstLeaf = root; // 保存找到的第一个叶子结点(k指针)
pcur = firstLeaf;
}
else // 链接时用叶子结点的rchild域存放指针
{
pcur->right = root;
pcur = pcur->right;
}
}
if(root->left) { leafLink(root->left);}
if(root->right) { leafLink(root->right);}
}
15、假设二叉排序树中采用如下数据结构存放节点,所有结点关键字不同,设计一个算法,求出指定关键字的结点所在的层次。
typedef int KeyType;
typedef char ElemType;
typedef struct tnode
{
KeyType key;
ElemType data;
tnode *lchild, *rchild:
}tnode;
int level(tnode *bt,KeyType k)
{
int h=0;
if(bt!=NULL)
{
h++;
while(bt->data!=k)
{
if(k<bt->data) {bt=bt->lchild;}
else{bt=bt->rchild;}
h++;
}
return h;
}
}
16、采用二叉树链式存储结构的叉树的递归交换左右子树和加值,如果节点值为偶数就左右子树交换如果节点值为奇数就加X。
void Slove(Node* T)
{
Node* temp;
if(T==Null)
{
return;
}
Slove(T->lchild);
Slove(T->rchild);
if(T->data%2==0)
{
//偶数则交换左右结点
temp=T->lchild;
T->lchild=T->rchild;
T->rchild=temp;
}
else
{
//奇数则计数
T-data+=X;
}
}
17、用非递归的方法写出计算二叉树叶子结点的个数
int Countleaf (BitNode t)
{
int count=0; //count用于给叶子结点计数
initstack(s); //初始化栈s
push(s,t); //将根结点t入栈
while(!emptystack(s) ) //当栈s不是空,就一直循环
{
pop(s,p); //将栈s最顶端的结点出栈,放入p
if(p->lchild==NULL && p->rchild==NULL) //p的左右孩子都是空
count++; //那么p就是叶子结点,count+1
if(p->lchild!=NULL) //如果p的左孩子不是空,则入栈
push(s,p->lchild);
if(p->rchild!=NULL) //如果p的右孩子不是空,则入栈
push(s,p->rchild);
}
return count;
}
18、分别用递归和非递归写出求二叉排序树的最小结点的算法 BitNode *findnodeMin(BitNode *node)
递归:
BitNode *findnodeMin(BitNode* node)
{
if (node->lchild == NULL)
return node;
findnodeMin(node->lchild);
}
非递归:
BitNode *findnodeMin(BitNode* node)
{
while(node->lchild!=null)
{
node=node->lchild;
}
return node;
}
19、编写算法求二叉树T的高度,数据结构用二叉链表表示。
非递归方法:
int Btdepth(BiTree T)
{
//采用层次遍历的非递归方法求解二叉树的高度
if(!T)
return 0; //树空,高度为0
int front=-1, rear=-1;
int last=0, level=0; //last指向下一层第一个结点的位置
BiTree Q[MaxSize] ; //设置队列Q,元素是二叉树结点指针且容量足够
Q[++rear]=T; //将根结点入队
BiTree P;
while(front<rear)
{
//队不空,则循环
p=Q[++front];//队列元素出队,即正在访问的结点
if(p->lchild)
Q[++rearl=p->lchild;//左孩子入队
if(p->rchild)
Q[++rear1=p->rchild;//右孩子入队
if(front==last)
{
//处理该层的最右结点
level++;//层数增1
Last=rear;//last指向下层
}
}
return level;
}
递归方法:
int Btdepth2 (BiTree T)
{
if (T==NULL)
return 0; //空树,高度为0
Ldep=Btdepth(T-> lchild); //左子树高度
rdep=Btdepth(T->rchild); //右子树高度
//树的高度为子树最大高度加根结点
if (ldep> rdep)
return ldep+1;
else
return rdep+1;
}
20、二叉树中所有结点之和
void sum (bitree *bt, int &s)
{
if(bt!=0)
{
s=s+bt->data;
sum(bt->lchild,s);
sum(bt->rchild,s);
}
}
21、二叉树是否为二叉排序树
int minnum=-32768,flag=l;
typedef struct node
{
int key; struct node *lchild,*rchild;
}bitree;
void inorder(bitree *bt)
{
if(bt!=0)
{
inorder(bt->lchild);
if(minnum>bt->key)
flag=0;
minnum=bt->key;
inorder(bt->rchild);
}
}
22、设计在链式存储结构上建立一棵二叉树的算法
typedef char datatype;
typedef struct node
{
datatype data;
struct node *lchild,*rchild;
} bitree;
void createbitree(bitree *&bt)
{
char ch;
scanf("%c",&ch);
if(ch==*#')
{
bt=0; return;
}
bt=(bitree*)malloc(sizeof(bitree));
bt->data=ch;
createbitree(bt->lchild);
createbitree(bt->rchild);
}
23、后序非递归遍历
void PostOrder(BiTree T )
{
InitStack(S);
p=T ;
r=NULL ;
while (p|| ! IsEmpty (S))
{
if(p)
{
push(S,p);
p=p->lchild;
}
else
{
GetTop (S,p);
if(p->rchild&&p->rchild!=r)
{
p=p->rchild;
push (S,p);
p=p->lchild;
}
else
{
pop(S,p);
visit(p->data);
r=p;
p=NULL;
}
}
}
}
24、先序非递归
void Preorder2 (BiTree T)
{
InitStack(S) ;
BiTree p=T ;
while(p||!IsEmpty(S))
{
if(p)
{
cout<<p->data;
Push(S,p);
p=p->lchild;
}
else
{
Pop (S,p);
p=p->rchild;
}
}
}
25、层次遍历
void LevelOrder(BiTree T)
{
InitQueue(Q);
BiTree p;
EnQueue(Q , T);
while (!IsEmpty (Q))
{
DeQueue (Q, p)
visit (p);
if(p->lchild!=NULL)
{
EnQueue(Q,p->lchild);
}
if(p->rchild!=NULL)
{
EnQueue(Q , p->rchild);
}
}
}
4.图部分
1、在邻接表表示的无向图中加入一条边(u,v)算法:AddEdge(adj,u,v)
其中:adj为邻接表表头数组,u、v是顶点号,为方便,u、v假定是合法的,且邻接表中没有边(u,v)(顶点号从1计,数组下标从0计,图的顶点数为n)。
void AddEdge(adj,u,v)
{
p=adj[u-1].firstarc;
while(p->nextarc)
{
p=p->nextarc;
}
q=(arcnode *)malloc(sizeof(arcnode));
q->adjvex=v;
q->nextarc=null;
p->nextarc=q;
p=adj[v-1].firstarc;
while(p->nextarc)
{
p=p->nextarc;
}
q=(arcnode *)malloc(sizeof(arcnode));
q->adjvex=u;
q->nextarc=null;
p->nextarc=q;
}
2、有n个结点的有向图(图的顶点号为1至n)用邻接表表示, 试完成从图中删除弧<u,v>的算法DelArc(adj,u,v)。(注:(1)为简便,假定弧<u,v>是存在的(2)adj为邻接表表头数组,数组下标从0计(3)结点的数据域名称可自己命名)
void DelArc(adj,u,v)
{
p=adj[u-1].firstarc;
q=NULL;
while(p->vex!=v)
{
q=p; p=p->nextarc;
}
if(q= =NULL)
adj[u-1].firstarc=p->nextarc;
else
q->nextarc=p->nextarc;
delete p;
}
3、完成一个有向图中增加一条弧的算法 InsertArc(adj,u,v,n)。 说明:adj 是图的邻接表表头数组(下标从 0 计),u,v 是弧<u,v>,顶点标号为 1 到 n,不要求判定弧是否存在,即假设插入数据是合法的。
InsertArc(adj , u, v)
{
r=new TreeNode;
r->adjvex=v;
r->next=adj[u-1].firstarc;
adj[u-1].firstarc=r;
}
4、图用邻接表存储,若己知顶点Vi和Vj,写出判断Vi与Vj是否相邻的算法status adjvcxVi-Vj(ALGraph C, adjvex Vi, adjvcx Vj)。
图的邻接表存储结构定义为:
#define MAX_VERTEX_NUM 20
typedef struct ArcNode
{
//边(弧)结点的类型定义
int adjvex;
//边(弧)的另一顶点的在数组中的位置
struct ArcNode *nextarc; //指向下一条边(弧)结点的指针
}ArcNode;
typcdef strict Vnode
{
//顶点结点和数组的类型定义
VertexType data; //顶点信息
ArcNode *finrstarc; //指向关联该顶点的边(弧)链表
}Vnode, AdjList[MAX_VERTEX_NUM];
typedef struct
{
AdjList vertices;
int vcxnum, arcnum; //图的当前顶点数和弧数
int kind; //图的种类标志
}ALGraph;
Status Judge(ALGraph *G,int i,int j)
{
arcNode *p=G->vertices[i].firstarc;
int find=0;
while(p!=null)
{
if(p->adjvex==j)
{
found=1;
break;
}
p=p->nextarc;
}
if(found)
{
printf(“相邻!”);
}
else
{
printf(“不相邻!”);
}
return OK;
}
5、求有向图中所有顶点入度的算法。
void FindIndegree(ALGraph G, int indegree[vexnum])
{
for(i=0;i<vexnum;i++)
{
indegree[i]=0;
}
for(i=0;i<vexnum;i++)
{
for(p=G.vertices[i].firstare;p;p=p->nextarc)
{
k=p->adjvex;
indegree[k+1]++;
}
}
}
6、判断图是否连通
DFS:
int count = 0;
void DFS(MGrap G. int i)
{
int j = 0;
visited[i] = 1;
count++;
for(j=0; j<G.numVertexes; j++)
{
if(G.arc[i][j]==1 && !visited[j])
{
DFS(G, j);
}
}
}
bool judge(){ //判断是否所有点已被遍历过
for(int i=1;i<=n;++i)
if(!vis[i])
return false;
return true;
}
BFS:
void bfs(int s){ //用队列广搜
queue<int> q;
q.push(s);
while(!q.empty()){
int x=q.front();
q.pop();
vis[x]=true;
for(int i=0;i<g[x].size();++i){
if(vis[g[x][i]]) g[x].erase(g[x].begin()+i);
else q.push(g[x][i]);
}
}
}
bool judge(){ //判断是否所有点已被遍历过
for(int i=1;i<=n;++i)
if(!vis[i])
return false;
return true;
}
7、BFS
bool visited[MAX_VERTEX_NUM];
void BFSTraverse (Graph G)
{
for (i=0;i<G.vexnum;++i)
visited[i]=FALSE;
InitQueue(Q) ;
for (i=0;i<G.vexnum;++i)
if (!visited [i])
BFS(G,i);
}
void BFS (Graph G, int v )
{
visit(v);
visited [v] =TRUE ;
Enqueue(Q,v);
while (!isEmpty (Q))
{
DeQueue (Q, v );
for(w=FirstNeighbor(G,v) ;w>=0; w=NextNeighbor(G,v,w))
if (!visited [w])
{
visit (w);
visited[w]=TRUE;
EnQueue (Q, w) ;
}
}
}
8、DFS
bool visited[MAX VERTEX NUM] ;
void DFSTraverse(Graph G)
{
for (v=0;v<G.vexnum;++v)
visited[v]=FALSE ;
for (v=0; v<G.vexnum;++v)
if(!visited [v])
DFS (G, v);
}
void DFS(Graph G, int v)
{
visit (v) ;
visited[v]=TRUE ;
for (w=FirstNeighbor (G, v) ; w>=0; w=NextNeighor (G, v , w))
if (!visited [w])
DFS (G , w) ;
}
5.查找部分
1、写一个递归的二分查找算法bina_s(d,x,l,h)
int bina_s(d,x,l,h)
{
int low=l; int high=h;
while(low<=high)
{
int mid=(low+high)/2;
if(d[mid]==x) return mid;
else if(d[mid]<x)
{
return bina_s(d,x,mid+1,high);
}
else
{
return bina_s(d,x,low,mid-1);
}
}
}
2、非递归二分查找
Int Binsch(ElemType A[],int n,KeyType K)
{
int low=0;
int high=n-1;
while(low<=high)
{
int mid=(low+high) /2;
if(K==A[mid].key)
retumn mid; //查找成功,返回元素的下标
else if(K<[mid].key)
high=mid-1; //在左子表上继续查找
else
low=mid+1; //在右子表上继续查找
}
return -1; //查找失败
}
6.栈和队列部分
1、一个队列用链表表示,队头与队尾指针分别是f和r,队有头结点,请完成一个队初始化和进队算法。
typedef struct Node
{
int data;
Node *next;
}Node;
void InitQueue(Node *f,Node *r,Node *Head)
{
f = Head;
r = f->next;
}
void InsetQueue(Node *node, Node *r)
{
r->next = node;
r = r->next;
}
2、已知循环队列(队列的顺序存储结构)类型的模块说明如下∶
#define MaxSize 100 // 最大队列长度
typedef struct
{
QElemType data[MaxSize]; // 循环队列的存储空间
int front; // 队头指针,若队列不空,指向队列头元素
int rear;//队尾指针,若队列不空,指向队列尾元素的下一个位置
} SqQueue;
基于上述类型模块,写出循环队列出队算法 int DeQueue(SqQueue &Q, QElemType &e),算法功能是∶ 若队列不空,则删除队列Q的队头元素,用e返回其值,算法返回一个int类型的值,该值为1表示操作成功,值为0表示操作失败。
int DeQueue(SqQueue &Q,QElemType)
{
if(Q.rear==Q.front)
return 0;//队列为空
e=Q.data[front];
Q.front=(Q.front+1)%MaxSize;
return 1;
}