中国农业大学数据结构期末复习算法题


文章目录



一、线性表

1、已知p指向双向循环链表中的一个结点,交换p所指向的结点及其前驱结点的顺序。

typedef struct DNode{
	int data;
	struct DNode* prior; //前驱 
	struct DNode* next;  //后继 
}DNode, *LinkList;

void swap(DNode *p) //交换p结点与其前驱结点的位置 
{
	DNode *q=p->prior; //q是p的前驱结点
	q->prior->next=p;
	p->prior=q->prior;
	p->next->prior=q;
	q->next=p->next;
	q->prior=p;
	p->next=q;
}

分三个阶段:
1、p与新前驱建立联系:
q->prior->next=p;
p->prior=q->prior;
.
2、q与新后继建立联系:
p->next->prior=q;
q->next=p->next;
.
3、p与q互连:
p->next=q;
q->prior=p;

注意:在交换过程中不能丢掉前后两端结点的地址,也就是在任何时候都应该可以得到两端的结点。
循环双向链表

2、HL是单链表的头指针,试写出删除头结点的算法。

ElemType DeleFront(LNode * & HL)
{
	if (HL==NULL){
   		cerr<<"空表"<<endl;
	exit(1);
}
	LNode* p=HL;
	HL=HL->next;
	ElemType temp=p->data;
	delete p;
	return temp;
} 

3、统计出单链表HL中结点的值等于给定值X的结点数。

int CountX(LNode* HL,ElemType x)
{
	int i=0;   //i为计数器
	LNode *p=HL;
	while(p){
		if(x==p->data) i++;
		p=p-next;
	} //出循环时i中的值即为x结点个数
	return i;
}

4、将一个结点类型为Lnode的单链表按逆序链接。

void contrary(Lnode *& HL)
{
	Lnode *p=HL;
	HL=NULL;
	while(p){
		Lnode *q=p;
		p=p->next;
		q->next=HL;
		HL=q;
	}
}

5、判断单链表中结点是否关于中心对称。

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->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--;
		else return 0;
	}
	return 1;
}

6、设计在单链表中删除值相同的多余结点的算法。

typedef int datatype;
typedef struct node{datetype data; struct node *next;}lklist;
void deleteRedundant(lklist *&head)
{
	lklist *p,*q,*s;
	for(p=head; p!=0; p=p->next){
		for(q=p->next,s=q;q!=0; ){
			if(q->data==p->data){
				s->next=q->next;
				free(q);
				q=s->next;
			}
			else{
				s=q;
				q=q->next;
			}
		}
	}
}

7、设单链表中有仅三类字符的数据元素(大写字母、数字和其它字符),要求利用原单链表中结点空间设计出三个单链表的算法,使每个单链表只包含同类字符。

typedef struct node{char data; struct node *next;}lklist;
void split(lklist *head, lklist *&ha, lklist *&hb, lklist *&hc)
{
	lklist *p;
	ha=0,hb=0,hc=0;
	for(p=head; p!=0; p=head){
		head=p->next;
		p->next=0;
		if('A'<=p->data && p->data<='Z'){p->next=ha; ha=p;}
		else if('0'<=p->data && p->data<='9') {p->next=hb;hb=p;}
		else {p->next=hc; hc=p;}
	}
}

8、设计两个有序单链表的合并排序算法。

typedef struct node{int data; struct node *next;} lklist;
void merge(lklist *ha, lklist *hb, lklist *&hc)
{
	lklist *s=hc=0;
	while(ha!=0 && hb!=0){
		if(ha->data < hb->data){
			if(s==0) hc=s=ha;
			else {s->next=ha; s=ha;}
			ha=ha->next;
		}
		else {
			if(s==0) hc=s=hb;
			else {s->next=hb; s=hb;}
			hb=hb->next;
		}
	}
	if(ha==0) s->next=hb;
	else s->next=ha;
}

9、设有两个集合A和集合B,要求设计生成集合C=A∩B的算法,其中集合A、B和C用链式存储结构表示。

typedef struct node{
	int data;
	struct node *next;
}lklist;
void intersection(lklist *ha, lklist *hb, lklist *&hc)
{
	lklist *p,*q,*t;
	for(p=ha,hc=0; p!=0; p=p->next){
		for(q=hb; q!=0; q=q->next)
			if(p->data == q->data) break;
		if(q!=0){
			t=(lklist*)malloc(sizeof(lklist));
			t->data=p->data;
			t->next=hc;
			hc=t;
		}
	}
}

10、设计在顺序存储结构上实现求子串算法。

void SubString(char s[],int start,int n,char t[])
{
	int i,j,length=strlen(s);
	if(start<1 || start>length) printf("The position is wrong.");
	if(start+n-1>length) printf("Too many characters to be copied.");
	else{
		for(i=start-1,j=0; i<start+n-1; i++,j++) t[j]=s[i];
		t[j]='\0';
	}
}

11、判断单链表中元素是否是递增。

int isincrease (lklist *head)
{
	lklist *p,*q;
	if(head==0 || head->next==0) return 1;
	for(q=head,p=head->next; p!=0; q=p,p=p->next){  //q在p前一个
		if(q->data > p->data)  //如果存在递减对
			return 0;
	}
	return 1;
}

二、栈和队列

三、数组和广义表

四、树和二叉树

1、在链式存储结构上建立一棵二叉树。

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

2、判断一棵二叉树是否是二叉排序树。

int minnum=-32768,flag=1;
typedef struct node{int key; struct node *lchild,*rchild;} bitree;
void inorder(bitree *bt)   //中序遍历二叉排序树,结点值应该是递增的
{
	if(bt){
		inorder(bt->lchild);
		if(minnum > bt->key) flag=0;
		minnum = bt->key;
		inorder(bt->rchild);
	}
}

3、在链式存储结构上建立一棵二叉排序树。

#definde N 10
typedef struct node{int key; struct node *lchild,*rchild;}bitree;
void BSTinsert(bitree *&bt, int key)
{
	if(bt==0){
		bt=(bitree*)malloc(sizeof(bitree));
		bt->key=key;
		bt->lchild=bt->rchild=0;
	}
	else if(key < bt->key) BSTinsert(bt->lchild,key);
	else BSTinsert(bt->rchild,key);
}
void CreateBST(bitree *&bt)
{
	for(int i=0;i<N;i++)
		BSTinsert(bt,random(100));
}

4、设计一个求结点x在二叉树中的双亲结点算法。

#define N 20
typedef struct node{
	int data;
	struct node *lchild, *rchild;
}bitree;
bitree *q[N];
int r=0,f=0,flag=0;
void preorder(bitree *bt, int x)
{
	if(bt!=0 && flag==0){
		if(bt->data==x){
			falg=1;
			return;
		}
		else{
			r=(r+1)%N;
			q[r]=bt;
			preorder(bt->lchild,x);
			preorder(bt->rchild,x);
		}
	}
}
void parent(bitree *bt,int x)
{
	int i;
	preorder(bt,x);
	for(i=f+1; i<=r; i++){
		if(q[i]->lchild->data==x || q[i]->rchild->data==x) break;
	}
	if(flag==0) printf("not found x.\n");
	else if(i<=r && flag==1) printf("parent: %d\n",q[i]->data);
	else printf("not parent.\n");
}

5、设计在链式存储结构上交换二叉树中所有结点左右子树的算法。

typedef struct node{int data; struct node *lchild,*rchild;} bitree;
void swap(bitree *bt)
{
	bitree *p;
	if(bt==0) return;
	swap(bt->lchild);
	swap(bt->rchild);
	p=bt->lchild; bt->lchild=bt->rchild; bt->rchild=p;
}

6、设计判断两个二叉树是否相同的算法。

typedef struct node{int data; struct node *lchild,*rchild;} bitree;
int judge(bitree *bt1, bitree *bt2)
{
	if(bt1==0 && bt2==0) return 1;
	if(bt1==0 || bt2==0 || bt1->data!=bt2->data) return 0;
	return judge(bt1->lchild,bt2->lchild)*judge(bt1->rchild,bt2->rchild);
}

7、设计求结点在二叉排序树中层次的算法。

int lev=0;
typedef struct node{int key; struct node *lchild,*rchild;}bitree;
void level(bitree *bt,int x)
{
	if(bt){
		lev++;
		if(x == bt->key) return;
		else if(x < bt->key) level(bt->lchild,x);
		else level(bt->rchild,x);
	}
}

8、设计在链式存储结构上统计二叉树中结点个数的算法。

void count(bitree *bt,&num)
{
	if(bt){
		num++;
		count(bt->lchild,num);
		count(bt->rchild,num);
		
	}
}

9、计算二叉树中所有结点值之和。

void sum(bitree *bt,long &sum)
{
	if(bt){
		sum+=bt->data;
		sum(bt->lchild,sum);
		sum(bt->rchild,sum);
	}


}

五、图

1、设计算法将无向图的邻接矩阵转为对应邻接表的算法。

typedef struct{int vertex[m]; int edge[m][m];int vexn,arcn;}adjmatrix;
typedef struct node1{int adjvex;int adjvertex;struct node1 *nextarc;}edgeode;
typedef struct node2{int data;edgenode *firstarc;}adjlist;
void adjmatrixtoadjlist(adjmatrix g1, adjlist g2[])
{
	int i,j;
	edgenode *p;
	for(i=0;i<g1.vexn;i++){
		g2[i].data=g1.vertex[i];
		g2[i].firstarc=NULL;
	}
	for(i=0;i<g1.vexn;i++){
		for(j=0;j<g1.vexn;j++){
			if(g1.edge[i][j]==1){
				p=(edgenode*)malloc(sizeof(edgenode));
				p->adjvertex=j;
				p->nextarc=g2[i].firstarc;
				g2[i].firstarc=p;
				p=(edgenode*)malloc(sizeof(edgenode));
				p->adjvertex=i;
				p->nextarc=g2[j].firstarc;
				g2[j].firstarc=p;
			}
		}
	}
}

六、查找

1、设计在顺序有序表中实现二分查找的算法。

struct record{int key;};
void bisearch(struct record r[], int n, int k)
{
	int low=0,high=n-1;
	int mid;
	while(low<=high){
		mid=(low+high)/2;
		if(r[mid]==k) return mid+1;
		else if(k < r[mid]) high=mid-1;
		else low=mid+1;
	}
	return 0;
}

2、设计在二叉排序树上查找结点X的算法。

//非递归
bitree *bstsearch(bitree *bt,int x)
{
	bitree*p=bt;
	while(p){
		if(x==p->data) return p;
		if(x<p->data) p=p->lchild;
		else p=p->rchild;
	}
	return 0;
}

七、排序

1、对一整型数组b[n]中的元素进行重新排列,将所有负数均调整到数组的低下标端,将所有正数均调整到数组的高下标端,若有零值,则置于两者之间,并返回数组中零元素的个数。

//调整整数数组中的元素顺序,并返回分界值i,使得所有小于x的数都在i左边,所有大于等于x的数都在i右边。
int arrange(int a[], int l ,int h, int x) //l,h分别为数据区的下界和上界
{
	int i,j,t;
	i=l, j=h;
	while(i<j){
		while(i<j && a[j]>=x) j--;
		while(i<j && a[i]<=x) i++;
		if(i<j){
			t=a[j]; a[j]=a[i]; a[i]=t;
		}
	}
	if(a[i]<x) return i;
	else return i-1;
}

int Rearrange_Countzero(int b[],int n)
{
	int p=arrange(b, 0, n-1, 0);   //p位置左边全为负数
	int q=arrange(b, p+1, n-1 ,1); //q位置右边全为正数
	return q-p;  //p和q中间都为0,q-p即为零元素个数
}

//或者
/*
int Rearrange_Countzero(int b[],int n)
{	int p=arrange(b, 0, n-1, 1); //p位置左边全为0和负数
	int q=arrange(b, 0, p, 0);   //q位置左边全为负数
	return p-q;  //p和q之间全为0,p-q即为零元素个数
}
*/

2、设有一组初始记录关键字序列(K1,K2,…,Kn),要求设计一个算法能够在O(n)的时间复杂度内将线性表划分成两部分,其中左半部分的每个关键字均小于Ki,右半部分的每个关键字均大于等于Ki。

void quickpass(int r[], int start, int end)
{
	int i=start,j=end,x=r[start];
	while(i<j){
		while(i<j && r[j]>x) j--;
		if(i<j) {r[i]=r[j]; i++;}
		while(i<j && r[i]<x) i++;
		if(i<j) {r[j]=r[i]; j--;}
	}
	r[i]=x;
} 

3、 在链式存储结构上设计直接插入排序算法。

void InsertSort(lklist *&head)
{
	lklist *s,*p,*q;
	int t;
	if(head==0 || head->next==0) return;
	else for(q=head,p=head->next; p!=0; p=q->next){
		for(s=head; s!=q->next; s=s->next){
			if(s->data > p->data) break;
		}
		if(s==q->next) q=p;
		else{
			q->next=p->next;
			p->next=s->next;
			s->next=p;
			t=p->data; p->data=s->data; s->data=t;
		}
	}
}

//法二
void InsertSort(lklist *&head)
{
	lklist *p,*pre,*q;
	p=head->next->next;  //保存链表中第二个元素
	head->next->next=NULL; //构造有序区,只有表中第一个元素
	while(p!=NULL){  //从表中第二个元素开始遍历
		q=p->next; //用q保存p的下一个元素
		pre=head;  //pre指向有序区
		while(pre!=NULL && pre->next->data <= p->data) //遍历有序区直至找到比p大的结点
			pre=pre->next;
		p->next=pre->next;
		pre->next=p;
		p=q;
	}
}

4、设计在链式结构上实现简单选择排序算法。

void SelectSort(lklist *&head)
{
	lklist *p,*q,*s;
	int min,t;
	if(head==0 || head->next==0) return;
	for(q=head; q!=0; q=q->next){
		min=q->data;
		s=q;
		for(p=q->next; p!=0; p=p->next){
			if(p->data < min){
				min=p->data;
				s=p;
			}
		}
		if(s!=q){
			t=s->data; s->data=q->data; q->data=t;
		}
	}
}

5、设计将所有奇数移到所有偶数之前的算法。

void quickpass(int r[],int s,int t)
{
	int i=s,j=t, x=r[s];
	while(i<j){
		while(i<j && r[j]%2==0) j--;
		if(i<j) {r[i]=r[j]; i++;}
		while(i<j && r[i]%2!=0) i++;
		if(i<j) {r[j]=r[i]; j--;}
	}
	r[i]=x;
}

6、设计在链式存储结构上合并排序的算法。

void mergesort(lklist *ha,lklist *hb.lklist *&hc)
{
	lklist *s=hc=0;
	while(ha!=0 && hb!=0){
		if(ha->data < hb->data){
			if(s==0) hc=s=ha;
			else {s->next=ha; s=ha;}
			ha=ha->next;
		}
		else{
			if(s==0) hc=s=hb;
			else {s->next=hb; s=hb;}
			hb=hb->next;
		}
	}
	if(ha!=0) s->next=ha;
	else s->next=hb;
}

7、设关键字序列(k1,k2,…,kn-1)是堆,设计算法将关键字序列(k1,k2,…,kn-1,x)调整为堆。

void adjustheap(int r[].int n)
{
	int j=n,i=j/2;
	int temp=r[j-1];  //temp为最后一层的最后一个叶子,即插入的x
	while(i>=1){
		if(temp>=r[i-1]) break;  //小根堆
		else {
			r[j-1]=r[i-1];
			j=i;
			i=i/2;
		}
	}
	r[j-1]=temp;
}
  • 47
    点赞
  • 202
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值