算法(三) :归并排序、树概念

一、归并排序

//       C语言版
//一趟归并
static void Merge(int *arr,int len,int gap)
{
	int low1 = 0;//第一个归并的的起始下标
	int high1 = gap-1;//第一个归并段的结尾下标
	int low2 = high1+1;//第二个归并段的起始下标
	int high2 = low2+gap-1<len-1 ? low2+gap-1 : len-1;//第二个归并段的结尾下标	
	int *brr = (int *)malloc(sizeof(int)*len);//存放归并好的数据
	int i = 0;//brr下标

	//有两个归并段
	while(low2 <= high2)
	{
		//两个归并段都还有数据
		while(low1<=high1 && low2<=high2)
		{
			if(arr[low1] <= arr[low2])
			{
				brr[i++] = arr[low1++];
			}
			else
			{
				brr[i++] = arr[low2++];
			}
		}

		//一个段数据归并完成,另一个还有数据
		while(low1 <= high1)
		{
			brr[i++] = arr[low1++];
		}

		while(low2 <= high2)
		{
			brr[i++] = arr[low2++];
		}

		low1 = high2+1;
		high1 = low1+gap-1;
		low2 = high1+1;
		high2 = low2+gap-1<len-1 ? low2+gap-1 : len-1;
	}

	//不足两个归并段
	while(low1 < len)
	{
		brr[i++] = arr[low1++];
	}

	for(i=0;i<len;i++)
	{
		arr[i] = brr[i];
	}
	free(brr);
}

void MergeSort(int *arr,int len)//O(nlogn),O(n),稳定
{
	for(int i=1;i<len;i*=2)//归并段的长度
	{
		Merge(arr,len,i);
	}
}

int main()
{
	int arr[] = {4,9,0,12,34,67,8,91,32,54,66,88,2};

	//SelectSort(arr,sizeof(arr)/sizeof(arr[0]));
	//HeapSort(arr,sizeof(arr)/sizeof(arr[0]));
	MergeSort(arr,sizeof(arr)/sizeof(arr[0]));
	Show(arr,sizeof(arr)/sizeof(arr[0]));

	return 0;
}
template<class Type>
void PrintArray(Type *ar,int n)   //打印数组
{
	for(int i = 0;i<n;++i)
	{
		cout<<ar[i]<<" ";
	}
	cout<<endl;
}

template<class Type>  //数组拷贝  di<---si
void CopyArray(Type *di,Type *si,int left,int right)  //  di<---si
{
	for(int i = left; i<=right; ++i)
	{
		di[i] = si[i];
	}
}

template<class Type>
void Merge(Type *di,Type *si,int left, int m,int right)
{
	int i = left, j = m+1;
	int k = i;
	while(i <= m && j <= right)
	{
		di[k++] = si[i] < si[j] ? si[i++]:si[j++];
	}

	while(i <= m)
	{
		di[k++] = si[i++];
	}

	while(j <= right)
	{
		di[k++] = si[j++];
	}
}

template<class Type>
void PassMerge(Type *br,Type *ar,int left,int right)
{
	if(left < right) // left = 1 right = 2
	{
		int mid = (right - left)/2 + left;
		PassMerge(br,ar,left,mid);// 1,1
		PassMerge(br,ar,mid+1,right);//2,2
		Merge(br,ar,left,mid,right);
		CopyArray(ar,br,left,right);
	}
}

template<class Type>
void MergeSort(Type *ar,int n)
{
	assert(ar != NULL && n >0);
	Type *br = new Type[n];
	PassMerge(br,ar,0,n-1);
	delete []br;
}


//非递归  归并排序
template<class Type>
void NicePassMerge(Type *di,Type *si,int n,int s)
{
	int i = 0;
	cout<<s<<endl;
	for(i = 0; i+2*s-1 <= n-1 ;i+=2*s)
	{
		Merge(di,si,i,i+s-1,i+2*s-1);
		cout<<i<<" "<<i+s-1<<" "<<i+2*s-1<<endl;
	}
	if(n-1 >  i+s-1)
	{
		Merge(di,si,i,i+s-1,n-1);
		cout<<i<<" "<<i+s-1<<" "<<n-1<<endl;
	}
	else
	{
		for(int j = i;j<n;++j)
		{
			di[j] = si[j];
		}
	}
}


template<class Type>
void NiceMergeSort(Type *ar,int n)
{
	assert(ar != NULL && n >0);
	Type *br = new Type[n];
	int s = 1;
	while(s < n)
	{
		NicePassMerge(br,ar,n,s); // 1
		s+=s;
		NicePassMerge(ar,br,n,s);
		s+=s;
	}
	delete []br;
}
int main()
{
	int ar[]={56,67,12,23,90,85,45,78,34,100,20};
	int n = sizeof(ar)/sizeof(ar[0]);

	PrintArray(ar,n);
	NiceMergeSort(ar,n);
	PrintArray(ar,n);
	return 0;
}

二、树的概念

概念:

  • 节点的度:一个节点含有的子树的个数称为该节点的度

  • 树的度:一棵树中,最大的节点的度称为树的度(上图B节点 3个度 最大);

  • 叶节点或终端节点:度为零的节点

  • 父亲节点或父节点:若一个节点含有子节点,则这个节点称为其子节点的父节点

  • 孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;

  • 兄弟节点:具有相同父节点的节点互称为兄弟节点;

  • 节点的层次:从根开始定义起,根为第1层,根的子节点为第2层,以此类推;

  • 树的高度或深度 :树中节点的最大层次(上图为5层);

  • 堂兄弟节点:父节点在同一层的节点互为堂兄弟

  • 森林:由m(m>=0)棵互不相交的树的集合称为森林;
    种类:

  • 无序树:树中任意节点的子节点之间没有顺序关系,这种树称为无序树,也称为自由树;

  • 有序树:树中任意节点的子节点之间有顺序关系,这种树称为有序树;

  • 二叉树:每个节点最多含有两个子树的树称为二叉树;

  • 完全二叉树:对于一颗二叉树,假设其深度为d(d>1)。除了第d层外,其它各层的节点数目均已达最大值,且第d层所有节点从左向右连续地紧密排列,这样的二叉树被称为完全二叉树;

  • 满二叉树:所有叶节点都在最底层的完全二叉树;

  • 平衡二叉树:当且仅当任何节点的两棵子树的高度差不大于1的二叉树;

  • 排序二叉树(二叉查找树)(英语:Binary Search Tree),也称二叉搜索树、有序二叉树)

二叉树的性质:

  • 在二叉树的第i层上至多有2^(i-1)个结点。
  • 深度为k的二叉树之多有(2^k)-1个结点。
  • 对任何一棵二叉树T,如果其终端结点数为n0,度为2的结点树为n2,则n0=n2+1
  • 具有n个结点的完全二叉树的深度为(logn)+1
  • 如果对一棵有n个结点的完全二叉树的结点按层序号遍历,对任意结点i有:
    如果i=1,则结点i是二叉树的根,无双亲;如果i>1,则其双亲是结点i/2。
    如果2i>n,则结点i无左孩子;否则其左孩子是结点2i。
    如果2i+1>n,则结点i无右孩子;否则其右孩子是结点2i+1.
先让我们看看原题的个任务介绍: Task 1: Sorting the LINEITEM table by External Merge Sort Consider two cases: 1) using 5 buffer pages in memory for the external merge sort; 2) using 129 buffer pages in memory for the external merge sort. In the implementation, each buffer page occupies 8K bytes. The ORDERKEY attribute of the LINEITEM table is assumed to be the sort key in the external merge sort. Please report the number of passes and also the running time of the external merge sort in each case. Task 2: Organizing the sorted LINEITEM table into disk pages Please use the page format for storing variable-length records to organize the LINEITEM table sorted in Task 1. In the implementation, each disk page occupies 1K bytes. For each page we maintain a directory of slots, with a pair per slot. Both “record offset” and “record length” are 4 bytes wide. Task 3: Building a B-Tree over LINEITEM disk pages by Bulk Loading. Please use bulk loading to build a B-Tree over the disk pages of the LINEITEM table, which are generated in Task 2. The ORDERKEY attribute of the LINEITEM table is used as the (search) key for building the B-Tree. In the B-Tree, each internal node corresponds to a page of 1K bytes, both key and pointer are 4 bytes wide. Please report the running time of the bulk loading. A query interface is required for checking the B-Tree. For a reasonable ORDERKEY value, please print out all the pages visited along the path to find the corresponding record. Please also report the running time of the search.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值