【2022---计算机考研】数据结构之基础算法背诵版

在这里插入图片描述


以下算法是数据结构中基础的算法也是很重要的,在某些学校的研究生考试中尤其是自命题考研中经常出现。以下算法也是其他算法的基础,建议都背会!

一、线性表

1. 逆转顺序表中的所有元素

算法思想:第一个元素和最后一个元素对调,第二个元素和倒数第二个元素对调,……,依此类推。

void Reverse(int A[], int n)
{
	int i, t;
	for (i=0; i < n/2; i++)
	{
		t = A[i];
		A[i] = A[n-i-1];
		A[n-i-1] = t;
	}
}

2. 删除线性链表中数据域为 item 的所有结点

算法思想:先从链表的第 2 个结点开始,从前往后依次判断链表中的所有结点是否满足条件,若某个 结点的数据域为 item,则删除该结点。最后再回过头来判断链表中的第 1 个结点是否满足条件,若 满足则将其删除。

void PurgeItem(LinkList &list)
{
	LinkList p, q = list;
	p = list->next; 
	while (p != NULL)
	{
		if (p->data == item) { 
			q->next = p->next; 
			free(p);
			p = q->next;
		} else {
			q = p;
			p = p->next;
		}
	}
	if (list->data == item)
	{
		q = list;
		list = list->next; free(q);
	}
}

3. 逆转线性链表

void Reverse(LinkList &list)
	{
	LinkList p, q, r;	
	p = list; q = NULL;
	while (p != NULL)
	{
		r = q; q = p;
		p = p->next; q->next = r;
	}
	list = q;
}

4. 复制线性链表(递归)

LinkList Copy(LinkList lista)
{
	LinkList listb;

	if (lista == NULL) return NULL;
	else {
		listb = (LinkList)malloc(sizeof(LNode)); 
		listb->data = lista->data;
		listb->next = Copy(lista->next); 
		return listb;
	}
}

5. 将两个按值有序排列的非空线性链表合并为一个按值有序的线性链表

LinkList MergeList(LinkList lista, LinkList listb)
{
	LinkList listc, p = lista, 	q = listb, r;
	// listc 指向 lista 和 listb 所指结点中较小者
	if (lista->data <= listb->data) { 
		listc = lista;
		r = lista;
		p = lista->next;
	} else {
		listc = listb; 
		r = listb;
		q = listb->next;
	}
	while (p != NULL && q != NULL){
		if (p->data <= q->data) { r->next = p;
		r = p;
		p = p->next;
	} else {
		r->next = q; r = q;
		q = q->next;
		}
	}
// 将剩余结点(即未参加比较的且已按升序排列的结点)链接到整个链表后面
	r->next = (p != NULL) ? p : q;   
	return listc;
}
 

二、树

树的结构:

typedef struct BiTNode{
	ElemType data;
	struct BiTNode * lchild,*rchild;  //左右孩子
}BiTNode, *BiTree ;

1. 二叉树的先序遍历(递归算法)

//先序遍历
void PreOrder(BiTree T){
	if(T!=NULL) {	//判断树是否为空
		visit(T);	//访问根结点
		PreOrder(T->lchild);//递归遍历左子树
		PreOrder(T->rchild);//递归遍历右子树
	}
}

2. 二叉树的中序遍历(递归算法)

//中序遍历
void InOrder(BiTree T){
	if(T!=NULL){	//判断树是否为空
		InOrder(T->lchild);	//递归遍历左子树
		visit(T);	//访问根结点
		InOrder(T->rchild);//递归遍历右子树
	}
}

3. 二叉树的后序遍历(递归算法)

//后序遍历
void PostOrder(BiTree T){
	if (T!=NULL){	//判断树是否为空
		PostOrder(T- >lchild);	//递归遍历左子树
		PostOrder(T- >rchild);	//递归遍历右子树
		visit(T) ;	//访问根结点
	}
}

4. 二叉树的先序遍历(非递归算法)

算法思想:若 p 所指结点不为空,则访问该结点,然后将该结点的地址入栈,然后再将 p 指向其左孩子结点;若 p 所指向的结点为空,则从堆栈中退出栈顶元素(某个结点的地址),将 p 指向其右孩子 结点。重复上述过程,直到 p = NULL 且堆栈为空,遍历结束。

#define MAX_STACK  50

void PreOrderTraverse(BTree T)
{
	BTree STACK[MAX_STACK], p = T;
	int	top = -1;
	while (p != NULL || top != -1){
		while (p != NULL){
			VISIT(p); 
			STACK[++top] = p;   //将当前指针p压栈
			p = p->lchild;	//指针p指向p的左孩子
		}
		p = STACK[top--];	//栈顶元素出栈
		p = p->rchild;		//p指针指向栈顶指针的右孩子
	}
}

5. 二叉树的中序遍历(非递归算法)

算法思想:若 p 所指结点不为空,则将该结点的地址 p 入栈,然后再将 p 指向其左孩子结点;若 p 所 指向的结点为空,则从堆栈中退出栈顶元素(某个结点的地址)送 p,并访问该结点,然后再将 p 指 向该结点的右孩子结点。重复上述过程,直到 p = NULL 且堆栈为空,遍历结束。

#define MAX_STACK  50

void InOrderTraverse(BTree T)
{
	BTree STACK[MAX_STACK], p = T;
	int	top = -1;//栈顶位置初始化

	while (p != NULL || top != -1){
		while (p != NULL){
			STACK[++top] = p; 
			p = p->lchild;	
		}
		p = STACK[top--]; 
		VISIT(p);		
		p = p->rchild;	
	}
}

6. 二叉树的后序遍历(非递归算法)

算法思想:当 p 指向某一结点时,不能马上对它进行访问,而要先访问它的左子树,因而要将此结点 的地址入栈;当其左子树访问完毕后,再次搜索到该结点时(该结点地址通过退栈得到),还不能对 它进行访问,还需要先访问它的右子树,所以,再一次将该结点的地址入栈。只有当该结点的右子 树访问完毕后回到该结点时,才能访问该结点。为了标明某结点是否可以访问,引入一个标志变量 flag,当 flag = 0 时表示该结点暂不访问,flag = 1 时表示该结点可以访问。flag 的值随同该结点的地 址一起入栈和出栈。因此,算法中设置了两个堆栈,其中 STACK1 存放结点的地址,STACK2 存放 标志变量 flag,两个堆栈使用同一栈顶指针 top,且 top 的初始值为 −1。

#define MAX_STACK	50

void PostOrderTraverse(BTree T)
{
	BTree STACK1[MAX_STACK], p = T;
	int	STACK2[MAX_STACK], flag, top = -1;
	while (p != NULL || top != -1){
		while (p != NULL) {		//节点第一次进栈
			STACK1[++top] = p; 
			STACK2[top] = 0;
			p = p->lchild;	//找到该节点的左孩子
		}
		p = STACK1[top];
		flag = STACK2[top--]; 
		if (flag == 0) {	//标记第二次进栈
			STACK1[++top] = p; 
			STACK2[top] = 1;	//标记第二次出栈
			p = p->rchild;
		} else {
			VISIT(p); 	//访问该节点的数据域
			p = NULL;
		}
	}
}

7. 二叉树的按层次遍历

算法思想:设置一个队列,首先将根结点(的地址)入队列,然后依次从队列中退出一个元素,每 退出一个元素,先访问该元素所指的结点,然后依次将该结点的左孩子结点(若存在的话)和右孩 子结点(若存在的话)入队列。如此重复下去,直到队列为空。

#define MAX_QUEUE  50

void LayeredOrderTraverse(BTree T){
	BTree QUEUE[MAX_QUEUE], p;
	int	front, rear;
	
	if (T != NULL){
		QUEUE[0] = T;
		front = -1;
		rear = 0;
		while (front < rear){
			p = QUEUE[++front]; 
			VISIT(P);
			if (p->lchild != NULL) QUEUE[++rear] = p->lchild;
			if (p->rchild != NULL) QUEUE[++rear] = p->rchild;
		}
	}
}
 

8. 建立二叉树(从键盘输入数据,先序遍历递归算法)

BTree CreateBT()
{
	char  ch; 
	BTree T;
	sacnf("%c", &ch); 
	if (ch == ' '){
		return NULL; 
	} else {
			if(!T = (BiNode*)malloc(sizeof(BiNode))){ //生成新的节点
				exit(1);
			}
			T->data	= ch;	//对数据域赋值
			T->lchild = CreateBT(); 	//递归创建左子树
			T->rchild = CreateBT(); 	//递归创建右子树
			return T;
	}
}

9. 建立二叉树(从数组获取数据)

BTree CreateBT(int A[], int i, int n)
{
	BTree p;
	if (i > n){
	return NULL; 
	}else {
		p = (BTree)malloc(sizeof(BTNode)); p->data = A[i];
		p->lchild = CreateBT(A, 2*i, n);
		p->rchild = CreateBT(A, 2*i+1, n); 
		return p;
	}
}

T = CreateBT(A, 1, n);
--------------------------------------------------------
BTree CreateBT(int A[], int n)
{
	int	i; BTree *pT;
// 对应 n 个结点申请可容纳 n 个指针变量的内存空间
	pT = (BTree *)malloc(sizeof(BTree)*n);
// 若数组中的某个元素不等于零,则申请相应的结点空间并进行赋值
	for (i=1; i <= n; i++)
	{
		if (A[i] != 0) {
			pT[i] = (BTree)malloc(sizeof(BTNode)); 
			pT[i]->data = A[i];
		} else {
			pT[i] = NULL;
		}
	}

// 修改结点的指针域的内容,使父结点指向左、右孩子结点
	for (i=1; i <= n; i++){
		if (pT[i] != NULL){
			pT[i]->lchild = pT[2*i]; 
			pT[i]->rchild = pT[2*i+1];
		}
	}
}
  1. 求二叉树的深度(递归算法)
int Depth(BTree T)
{
	int ldepth, rdepth;

	if (T == NULL){
	return 0; 
	}	else {
		ldepth = Depth(T->lchild); 
		rdepth = Depth(T->rchild); 
		if (ldepth > rdepth){
			return ldepth+1; 
		}else {
			return rdepth+1;
		}
	}
}

10. 求二叉树的深度(递归算法)

int treeDepth(BiTree T){
	if (T == NULL) {	//判断树是否为空
		return 0;
	}else {
		int l = treeDepth(T->lchild);
		int r = treeDepth(T->rchild);
		//树的深度=Max(左子树深度,右子树深度)+1
		return l>r ? 1+1 : r+1;
	}
}

11. 求二叉树的深度(非递归算法)

算法思想:对二叉树进行遍历,遍历过程中依次记录各个结点所处的层次数以及当前已经访问过的 结点所处的最大层次数。每当访问到某个叶子结点时,将该叶子结点所处的层次数与最大层次数进 行比较,若前者大于后者,则修改最大层次数为该叶子结点的层次数,否则不作修改。遍历结束时, 所记录的最大层次数即为该二叉树的深度。本算法使用的是非递归的中序遍历算法(其它遍历顺序 也可以)。

#define MAX_STACK	50

int Depth(BTree T)
{
	BTree STACK1[MAX_STACK], p = T; 
	int	STACK2[MAX_STACK];
	int	curdepth, maxdepth = 0, top = -1;

	if (T != NULL){
		curdepth = 1;
		while (p != NULL || top != -){
			while (p != NULL){
				STACK1[++top] = p;
				STACK2[top] = curdepth;
				p = p->lchild; 
				curdepth++;
			}
			p = STACK1[top];
			curdepth = STACK2[top--];
			if (p->lchild == NULL && p->rchild == NULL) {
				if (curdepth > maxdepth){
					maxdepth = curdepth; 
					p = p->rchild;
					curdepth++;
				}
			}
		}
	}
	return maxdepth;
}

12. 求结点所在层次

算法思想:采用后序遍历的非递归算法对二叉树进行遍历,遍历过程中对每一个结点判断其是否为 满足条件的结点,若是满足条件的结点,则此时堆栈中保存的元素个数再加 1 即为该结点所在的层次。

#define MAX_STACK	50

int LayerNode(BTree T, int item)
{
	BTree STACK1[MAX_STACK], p = T;
	int	STACK2[MAX_STACK], flag, top = -1;

	while (p != NULL || top != -1){
		while (p != NULL){
			STACK1[++top] = p; 
			STACK2[top] = 0;
			p = p->lchild;
		}
		p = STACK1[top];
		flag = STACK2[top--]; 
		if (flag == 0) {
			STACK1[++top] = p; 
			STACK2[top] = 1;
			p = p->rchild;
		} else {
			if (p->data == item) return top+2;
			p = NULL;
		}
	}
}

13. 交换二叉树中所有结点的左右子树的位置

算法思想:按层次遍历二叉树,遍历过程中每当访问一个结点时,就将该结点的左右子树的位置对 调。

#define MAX_QUEUE	50

void ExchangeBT(BTree T){
	BTree QUEUE[MAX_QUEUE], temp, p = T;
	int	front, rear;

	if (T != NULL){
		QUEUE[0] = T;
		front = -1;
		rear = 0;
		while (front < rear){
			p = QUEUE[++front]; 
			temp = p->lchild;
			p->lchild = p->rchild; 
			p->rchild = temp;
			if (p->lchild != NULL){
				 QUEUE[++rear] = p->lchild;
			 }
			if (p->rchild != NULL) {
				 QUEUE[++rear] = p->rchild;
			}
		}
	}
}
 

14. 删除二叉树中以某个结点为根结点的子树

算法思想:先序遍历找到符合条件的结点(其它遍历方法亦可),然后删除以该结点为根结点的子树。 最后把该结点的父结点的相应的指针域置为 NULL。为此,需在算法中设置一个指针变量用以指示当 前结点的父结点。

#define MAX_STACK	50

BTree DeleteSubtree(BTree &T, int item)
{
	BTree STACK[MAX_STACK], q, p = T;
	int	top = -1;

	if (T->data == item){
		DestroyBT(T); T = NULL;
		return NULL;
	}  else {
		while (p != NULL || top != -1){
			while (p != NULL){
				if (p->data == item){
					if (q->lchild == p){
						q->lchild = NULL; 
					}else {
						q->rchild = NULL; DestroyBT(p);
						return T;
					}
				}
				STACK[++top]= p;
				q = p;
				p = p->lchild;
			}
			q = STACK[top--];
			p = q->rchild;
		}
	}
}
 

三、查找

1. 顺序查找的递归算法

int RecurSeqSearch(int A[], int n, int key, int i) {
	if (i >= n){
		return -1; 
	} else 	if(A[i] == key){
		return i; 
	}else
		return RecurSeqSearch(A, n, key, i+1);
}

pos = RecurSeqSearch(A, n, key, 0);

2. 折半查找

int BinSearch(int A[], int n, int key){
	int low=0, high=n-1, mid;

	while (low <= high){
		mid = (low+high)/2; 
		if (key == A[mid]){
			return mid; 
			if (key > A[mid]){
				low = mid + 1; else
				high = mid – 1;
			}
			return -1;
		}
	}
}

3. 折半查找的递归算法

int RecurBinSearch(int A[], int low, int high, int key){
	int mid;

	if (low > high){ 
		return -1;
	}else {
		mid = (low+high)/2; 
		if (key == A[mid]){
			return mid; 
		}
		if (key > A[mid]) {
			return RecurBinSearch(A, mid+1, high, key); else
			return RecurBinSearch(A, low, mid-1, key);
		}
	}
}

pos = RecurBinSearch(A, 0, n-1, key);
 

4. 在按值递增排列且长度为 n 的线性表中折半查找并插入一元素

void BinInsert(int A[], int &n, int key){
	int j, low=0, high=n-1, mid;
	
	while (low <= high)	{
		mid = (low+high)/2; 
		if (key > A[mid]){
			low = mid + 1; else
			high = mid – 1;
		}
	}

	for (j=n; j > low; j--){
		A[j] = A[j-1];
		A[low] = key; 
		n++;
	}
}

5. 在按值递增排列且长度为 n 的线性表中折半查找值不小于 key 的最小元素

void BinSearch(int A[], int n, int key){
	int low=0, high=n-1, mid;

	while (low <= high){
		mid = (low+high)/2; 
		if (key == A[mid]){
			return mid; 
		}
		if (key > A[mid]){
			low = mid + 1; 
		} else{
			high = mid – 1;
		}
	}

	if (low <= n-1) {
		return low;
	}  else  {
		return -1;
	}
}
 

四、图

1. 深度优先算法

算法思想:
树的深度优先遍历 (先根、后根) : 从根节点出发,能往更深处走就尽量往深处走。每当访问一个结点的时候,要检查是否还有与当前结点相邻的且没有被访问过的结点,如果有的话就往下一层钻。
图的深度优先遍历类似于树的先根遍历。

bool visited [MAX_ _VERTEX_ _NUM]; // 访问标记数组
void DFSTraverse(Graph G){	
//对图G进行深度优先遍历
	for(v=0; v<G. vexnum; ++v)
		visited [v]=FALSE;	//初始化已访问标记数据
	for(v=0; v<G. vexnum; ++v)	//本代码中是从v=0开始遍历
		if(!visited[v])
			DFS(G,v);
}
void DFS(Graph G,int v){	//从顶点v出发,深度优先遍历图G
	visit(v);	//访问顶点v
	visited [v]=TRUE;	//设已访问标记
	for (w=FirstNeighbor(G,v);W>=0;w=NextNeighor(G,v,w))
	if(!visited[w]){ 	//w为u的尚未访问的邻接顶点
		DFS(G,w);
	} //if
}

2. 广度优先算法

在这里插入图片描述

广度优先遍历(Breadth-First. -Search, BFS)要点:

  1. 找到与一个顶点相邻的所有顶点
  2. 标记哪些顶点被访问过
  3. 需要一个辅助队列 .

Notes

1.FirstNeighbor(G,x): 求图G中顶点x的第一个邻接点,若有则返回顶点号。 若x没有邻接点或图中不存在x,则返回-1。
2.NextNeighbor(G,x,y): 假设图G中顶点y是顶点x的一个邻接点,返回除y之外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1。

bool visited [MAX_ VERTEX_ _NUM];
//访问标记数组
void BFSTraverse(Graph G){ //对图G进行广 度优先遍历
	for( i=0; i<G. vexnum;++i)
		visited [i]=FALSE;	//访问标记数组初始化
	InitQueue(Q);	//初始化辅助队列Q
	for( i=0; i<G. vexnum;++i)	//从0号顶点开始遍历
		if(!visited[i])	//对每个连通分量调用一次BFS
			BFS(G,i);	//vi未访问过,从vi开始BFS
}
//广度优先遍历
void BFS(Graph G,int v){ //从顶点v出发, 广度优先遍历图G
	visit(v);	//访问初始顶点v
	visited [v]=TRUE;	//对v做已访问标记
	Enqueue(Q,v);	//顶点v入队列Q
	while( ! isEmpty(Q)){
		DeQueue(Q,v);	//顶点v出队列
		for(w=FirstNeighbor(G, v) ;W>=0 ;w=NextNe ighbor(G,V,W))	
		//检测v所有邻接点
		if( !visited[w]){ //w为v的尚未访问的邻接顶点
			visit(W);	//访问顶点w
			visited [w]=TRUE ;//对w做已访问标记
			EnQueue(Q,w); //顶点w入队列
		}//if
	}//while
}

五、排序

在这里插入图片描述

1. 插入排序

算法思想:第 i 趟插入排序为:在含有 i − 1 个元素的有序子序列中插入一个元素,使之成为含有 i 个元素的有序子序列。在查找插入位置的过程中,可以同时后移元素。整个过程为进行 n − 1 趟插入, 即先将整个序列的第 1 个元素看成是有序的,然后从第 2 个元素起逐个进行插入,直到整个序列有序 为止。

void InsertSort(int A[], int n){
	int i, j, temp;

	for (i=1; i <= n-1; i++){
		if (A[i] < A[i-1]){
			j = i-1; 
			temp = A[i];
		}
		while (j >= 0 && temp < A[j]){
			A[j+1] = A[j]; j--;
		}
		A[j+1] = temp;
	}
}

2. 折半插入排序

算法思想:算法同直接插入排序,只不过使用折半查找的方法来寻找插入位置。

void BinInsertSort(int A[], int n){
	int i, j, low, high, mid, temp;

	for (i=1; i <= n-1; i++){
		temp = A[i]; 
		low= 0; 
		high = i – 1;
		while (low <= high){
			mid = (low+high)/2; 
			if (temp > A[mid]){
				low = mid + 1; 
			}else
			high = mid – 1;
		}
		for (j=i; j > low; j--)
		A[j] = A[j-1];
		A[low] = temp;
	}
}
 

3. 冒泡排序

详情查看:
十大排序算法之(一)-----冒泡排序
在这里插入图片描述
算法思想:首先将第 1 个元素和第 2 个元素进行比较,若前者大于后者,则两者交换位置,然后比较 第 2 个元素和第 3 个元素。依此类推,直到第 n − 1 个元素和第 n 个元素进行过比较或交换为止。上 述过程称为一趟冒泡排序,其结果是使得 n 个元素中值最大的那个元素被安排在最后一个元素的位置 上。然后进行第二趟排序,即对前 n − 1 个元素进行同样的操作,使得前 n − 1 个元素中值最大的那 个元素被安排在第 n − 1 个位置上。一般地,第 i 趟冒泡排序是从前 n − i + 1 个元素中的第 1 个元素 开始,两两比较,若前者大于后者,则交换,结果使得前 n − i + 1 个元素中最大的元素被安排在第 n
− i + 1 个位置上。显然,判断冒泡排序结束的条件是“在一趟排序中没有进行过交换元素的操作”, 为此,设立一个标志变量 flag,flag = 1 表示有过交换元素的操作,flag = 0 表示没有过交换元素的操 作,在每一趟排序开始前,将 flag 置为 0,在排序过程中,只要有交换元素的操作,就及时将 flag 置 为 1。因为至少要执行一趟排序操作,故第一趟排序时,flag = 1。

void BubbleSort(int A[], int n){
	int i, j, temp, flag = 1;
	
	for (i=n-1; i >= 1 && flag == 1; i--){
		flag = 0;		//表示本趟冒泡是否发生交换的标志
		for (j=0; j < i; j++){	//表示一趟冒泡
			if (A[j] > A[j+1]){	//若为逆序
				temp = A[j]; //交换
				A[j] = A[j+1];
				A[j+1] = temp; 
				flag = 1;
			}
		}
	}
}

4. 快速排序

详情查看:
十大排序算法之(二)----快速排序

算法思想:在参加排序的序列中任意选择一个元素(通常称为分界元素或基准元素),把小于或等于 分界元素的所有元素都移到分界元素的前面,把大于分界元素的所有元素都移到分界元素的后面, 这样,当前参加排序的序列就被划分成前后两个子序列,其中前一个子序列中的所有元素都小于后 一个子序列的所有元素,并且分界元素正好处于排序的最终位置上。然后分别对这两个子序列递归 地进行上述排序过程,直到所有元素都处于排序的最终位置上,排序结束。

void QuickSort(int A[], int n){
	QSort(A, 0, n-1);
}

void QSort(int A[], int low, int high){
	int pivotloc;

	if (low < high){
		pivot = Partition(A, low, high); 
		QSort(A, low, pivotloc-1); 
		QSort(A, pivotloc+1, high);
	}
}

int Partition(int A[], int low, int high){
	int pivot;

	pivot = A[low];
	// 从线性表的两端交替地向中间扫描
	while (low < high){
		while (low < high && A[high] >= pivot) high--;
		A[low] = A[high];
		while (low < high && A[low] <= pivot) low++;
		A[high] = A[low];
	}
	A[low] = pivot; 
	return low;
}
 

5. 选择排序

在这里插入图片描述

算法思想:第 i 趟排序从序列的后 n − i + 1(i = 1, 2, …, n − 1)个元素中选择一个值最小的元素与该 个元素的第 1 个元素交换位置,即与整个序列的第 i 个元素交换。依此类推,直到 i = n − 1 为止。也 就是说,每一趟排序从从未排好序的那些元素中选择一个值最小的元素,然后将其与这些未排好序 的元素中的第 1 个元素交换位置。

void SelectSort(int A[], int n){
	int i, j, min, temp;

	for (i=0; i < n; i++){
		min = i;
		for (j=i+1; j < n; j++){
			if (A[min] > A[j]) min = j;
		}
		if (min != i){
			temp = A[min]; 
			A[min] = A[i]; 
			A[i] = temp;
		}
	}
}
 

6. 堆排序

在这里插入图片描述

void HeapSort(int A[], int n){
	int i, temp;

	// 建立大顶堆
	for (i = n/2; i >= 1; i--) HeapAdjust(A,i,n);
	for (i = n-1; i >= 1; i--){
		temp  = A[1]; 
		A[1]  = A[i+1];
		A[i+1] = temp;
		// 将 A[1..i] 重新调整为大顶堆
		HeapAdjust(A,1,i);
	}
}

void HeapAdjust(int A[], int low, int high){
	int i, temp;

	temp = A[low];
	for (i=2*low; i <= high; i=i*2){
		// 令 i 为关键字较大的记录的下标
		if (i < high && A[i] < A[i+1]){
		 	i++;
		 }else if (temp >= A[i]) {
		 	break;
		} else if {
			A[low] = A[i]; 
			low = i;
		}
	}
	A[low] = temp;	// 插入
}
一、选择题 1. 散列文件使用散列函数将记录的关键字值计算转化为记录的存放地址,因为散列函数是一对一的关系,则选择好的( )方法是散列文件的关键。【哈尔滨工业大学 2001二、5 (2分)】 A. 散列函数 B. 除余法中的质数 C. 冲突处理 D. 散列函数和冲突处理 2. 顺序文件采用顺序结构实现文件的存储,对大型的顺序文件的少量修改,要求重新复制整个文件,代价很高,采用( )的方法可降低所需的代价。【北京邮电大学 2000 二、8 (20/8分)】 A. 附加文件 B. 按关键字大小排序 C. 按记录输入先后排序 D. 连续排序 3. 用ISAM组织文件适合于( )。【中科院软件所 1998】 A.磁带 B.磁盘 4.下述文件中适合于磁带存储的是( )。【中科院计算所 2000 一、7(2分)】 A. 顺序文件 B. 索引文件 C. 散列文件 D. 多关键字文件 5. 用ISAM和VSAM组织文件属于( )。 A. 顺序文件 B. 索引文件 C. 散列文件 【中国科技大学 1998 二、5(2分) 中科院计算所 1998 二、5(2分)】 6. ISAM文件和VASM文件属于( )。【山东大学 2001 二、5 (1分)】 A. 索引非顺序文件 B. 索引顺序文件 C. 顺序文件 D. 散列文件 7. B+树应用在( )文件系统中。【北京邮电大学 2001 一、1(2分)】 A. ISAM B. VSAM 二、判断题 1. 文件是记录的集合,每个记录由一个或多个数据项组成,因而一个文件可看作由多个记录组成的数据结构。【长沙铁道学院 1998 一、5 (1分)】 2. 倒排文件是对次关键字建立索引。【南京航空航天大学 1997 一、10(1分)】 3. 倒排序文件的优点是维护简单。【南京航空航天大学 1995 五、10(1分)】 4. 倒排文件与多重表文件的次关键字索引结构是不同的。【西安交通大学 1996 二、6 (3分)】 5. Hash表与Hash文件的唯一区别是Hash文件引入了‘桶’的概念。【南京航空航天大学1996六10(1分)】 6. 文件系统采用索引结构是为了节省存储空间。【北京邮电大学 2000 一、10 (1分)】 7. 对处理大量数据的外存介质而言,索引顺序存取方法是一种方便的文件组织方法。 【东南大学 2001 一、1-10 (1分)】 8. 对磁带机而言,ISAM是一种方便的稳健组织方法。【中科院软件所 1997 一、10(1分)】 9. 直接访问文件也能顺序访问,只是一般效率不高。【北京邮电大学 2002 一、10(1分)】 10. 存放在磁盘,磁带上的文件,即可以是顺序文件,也可以是索引结构或其他结构类型的文件。 【山东大学 2001 一、7 (1分)】 11. 检索出文件中的关键码值落在某个连续的范围内的全部记录,这种操作称为范围检索。对经常需要做范围检索的文件进行组织,采用散列法优于顺序检索法。【中山大学 1994 一、5 (2分)】 三、填空题 1. 文件可按其记录的类型不同而分成两类,即______和______文件。 【西安电子科技大学 1998 二、6(3分)】 2. 数据库文件按记录中关键字的多少可分成______和______两种文件。 【燕山大学 1998 一、10 (2分)】 3. 从用户的观点看,文件的逻辑结构通常可以区分为两类:一类是如 dBASE 中数据库文件那样的文件组织结构,称为_(1)_文件;另一种是诸如用各种文字处理软件编辑成的文本文件,称为__(2)_文件。从文件在存储器上的存放方式来看,文件的物理结构往往可区分为三类,即_(3)_,_(4)_和_(5)_。B+ 树适用于组织_(6)_的索引结构,m 阶B+ 树每个结点至多有_(7)_个儿子,除根结点外每个结点至少有 (8) 个儿子,根结点至少有_(9)_个儿子,有k个儿子的结点必有_(10) 个关键码。 【山东工业大学 1996 一、4(5分)】 4. 文件由______组成;记录由______组成。【大连海事大学 1996 (2分)】 5. 物理记录之间的次序由指针相链表示的顺序文件称为 ______。【燕山大学 1998 一、11 (1分)】 6. 顺序文件中,要存取第I个记录,必须先存取______个记录。【哈尔滨工业大学 2001 一、4 (2分)】 7. 索引顺序文件既可以顺序存取,也可以______存取。【武汉大学2000 一、10】 8. 建立索引文件的目的是______。【中山大学 1998 一、12 (1分)】 9. 索引顺序文件是最常用的文件组织之一,通常用____结构来组织索引。【长沙铁道学院1998二、6(2分)】 10. 倒排序文件的主要优点在于______。【山东工业大学1995一、3(1分)】 11. 检索是为了在文件中寻找满足一定条件的记录而设置的操作。检索可以按______检索,也可以按______检索;按______检索又可以有_________检索和_________检索。【山东大学 1999 一、1 (5分)】 12. 散列检索技术的关键是______和 ______。【山东工业大学 1995 一、2 (2分)】 13. VSAM系统是由______、______、______构成的。【北京科技大学 1997 一、9】 14. VSAM(虚拟存储存取方法)文件的优点是:动态地______,不需要文件进行______,并能较快地______进行查找。【山东大学 2001 三、4 (2分)】 四、应用题 1. 文件【山东工业大学 1998 一、1-1(2分)】 2. 文件存储结构的基本形式有哪些?一个文件采用何种存储结构应考虑哪些因素? 【燕山大学 1999 二、4(4分)】 3. 名词解释:索引文件【哈尔滨工业大学 2000 一、4 (3分)】 4. 什么是索引顺序文件?【哈尔滨工业大学2001三、5(3分)】【
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦幻蔚蓝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值