数据结构(三) 排序查找

排序

插入排序

//插入排序
直接插入排序
#define maxsize 1024  //文件最大长度 
typedef int keytype;  //设key值为整型 
typedef struct  //记录类型 
{
	keytype key;  //记录关键字 
	...          //记录其他域 
}Retype;
typedef struct //文件或表的类型 
{
	Retype R[maxsize+1];  //文件存储空间 
	int len;  //当前记录数 
}sqfile;

void Insort(sqfile F)  //对顺序文件F直接插入排序的算法 
{
	int i, j;
	for(i = 2; i <= F; i++)  //插入n-1个记录 
	{
		F.R[0] = F.R[i];  //待插入记录先存于监视哨 
		j = i - 1;
		while(F.R[0].key < F.R[j].key)  //key比较 
		{
			F.R[j + 1] = F.R[j];  //记录顺序后移 
			j--;
		}
		F.R[j+1] = F.R[j];  //原R[i]插入j+1位置 
	}
}

折半插入排序
void Binsort(sqfile F)  //对文件F进行折半查找的算法 
{
	int i, j, low, high, mid;
	for(i = 2; i <= F; i++)  //插入n-1个记录 
	{
		F.R[0] = F.R[i];  //带插入记录存入监视哨 
		low = 1; high = i-1;
		while(low <= high)  //查找R[i]的位置 
		{
			mid = (low + high) / 2;
			if(F.R[0].key >= F.R[mid].key)
				low = mid + 1;  //调整下界 
			else
				high = mid - 1;  //调整上界 
		}
		for(j = i - 1; j >= low; j--)
			F.R[j+1] = F.R[j];  //记录顺移 
		F.R[low] = F.R[0];   //原R[i]插入low位置 
	}
}


链表插入排序 
typedef struct node  //存放记录的节点 
{
	keytype ley;  //记录关键字 
	...  //记录其他域 
	struct node *next;  //链指针 
}Lnode, *linklist;

void Linsertsort(linklist L)  //链表插入排序算法 
{
	linklist p, q, r, u;
	p = L->next;  //p为描述节点指针 
	L->next = NULL:  //置字表为空 
	while(p)  //若待排序节点存在 
	{
		r = L; q = L->next;  //r为q的前驱指针 
		while(q&&p->key <= p->key)  //找p节点的位置 
		{r = q; q = q->next;}
		u = p->next;
		p->next = q;  //p节点为q节点的前驱插入 
		r->next = p;
		p = u; 
	}
}


Shell排序 
void Shellsort(sqfile F)  //对顺序文件F按Shell方法排序的算法 
{
	int i, j, d;
	d = F.len / 2;  //第一次增量 
	while(d >= 1)
	{
		for(i = d+1; i <= F.len; i++)  //本趟的希尔排序 
		{
			F.R[0] = F.R[i];
			j = i - d;
			while((j > 0) && (F.R[0].key < F.R[j].key))
			{
				F.R[j+d] = F.R[j];  //记录移动 
				j = j - d;
			}
			F.R[j+d] = F.R[0];
		}
		d = d / 2;  //形成新的增量 
	 } 
}


冒泡排序

//冒泡排序
void Bubsort(sqfile F)  //对顺序文件气泡排序的算法 
{
	int i, flag;  //flag为记录交换次数的标记 
	Retype temp;
	for(j = F.len; i >= 2; i--)  //最多n-1趟排序 
	{
		flag = 0;
		for(j = 1; j <= i-1; j++)  //一趟气泡排序 
		if(F.R[j].key > F.R[j+1].key)  //两辆比较 
		{
			temp = F.R[j];  //R[j] <=> R[j+1]
			F.R[j] = F.R[j+1];
			F.R[j+1] = temp;
			flag = 1;
		}
		if(flag == 0) break;  //无记录交换时排序完毕 
	 } 
}

快速排序

//快速排序
typedef struct  //栈元素类型 
{
	int low, high;  //存放末排子表的上下界 
}stacktype;

int qkpass(sqfile F, in low, int high)
//对文件F中当前子表(R[low]...R[high])一趟快速排序的算法 
{
	int i = low, j = high;
	keytype x = F.R[low].key;  //存入基准key 
	F.R[0] = F.R[low];  //存入基准记录 
	while(i < j)
	{
		while(i < j && x <= F.R[j].key)  y--;  //逆序比较 
		if(i < j) F.R[i] = F.R[j];  //比x小的key左移 
		while(i < j && x >= F.R[i].key)  i++;  //正序比较 
		if(i < j) F.R[j] = F.R[i];  //比x大的key右移 
	}
	F.R[i] = F.R[0];  //基准记录存入第i位置 
	return (i);  //返回基准位置 
}

void qksort(sqfile F)  //对文件F快速排序的算法(非递归) 
{
	int i, low, high;
	stacktype u;  //栈元素 
	Clearstack(S);  //置栈空 
	u.low = 1; u.high = F.len;
	Push(S, u);
	while(!Emptystack(S))
	{
		u = Pop(S);  //退栈 
		low = u.low; high = u.high;  //取当前表的上下界 
		while(low < high)
		{
			i = qkpass(F, low, high);  //对当前子表的一趟快排
			if(i + 1 , high)
			{
				u.low = i + 1; u.high = high;  //i位置的右部上下界进栈 
				Push(S, u);
			}
		 }
		 high = i - 1;  //排当前位置的左部 
	}
}


选择排序

//选择排序
void Slectsort(sqfile F)
{
	int i, j, k;
	Retype temp;
	for(i = 1; i < F.len; i++)  //选择n-1趟 
	{
		j = i;  //j为本趟选择的最小key记录的序号 
		for(k = i + 1; k < F.len; k++)  //本趟选择 
			if(F.R[k].key < F.R[j].key)  j = k;
		if(i != j)
		{
			temp = F.R[i];
			F.R[i] = F.R[j];
			F.R[j] = temp; 
		}
	}
}

堆排序

//堆排序
筛选算法描述
void ADjust(sqfile F, int s, int n)  //将(F.R[s]...F.R[n])调整成大根堆的算法 
{
	Retype temp;
	int j;
	temp = F.R[s];  //暂存F.R[s] 
	j = 2*s;  //令j为s节点的左子序号 
	while(j <= n)
	{
		if(j < n && F.R[j+1].key > F.R[j].key)  j++;  //令j为s的左右孩子key的最大者编号 
		if(F.R[j].key > temp.key)
		{
			F.R[s] = F.R[j];   //R[j] => R[s] 
			s = j; j = 2 * s;  //置新的调整点 
		}
		else break;  //调整完毕,退出循环 
	}
	F.R[s] = temp;  //最初的根回归 
 } 


void Heapsort(sqfile F)  //对顺序文件F的堆排序算法 
{
	int i;
	Retype temp;
	for(i ;= F.len / 2; i >= 1; i--)
	{
		Adjust(F, i, F.len)  //调整(R[i]...R[n])为堆 
	}
	for(i = F.len; i >= 2; i--)  //选择n-1次 
	{
		temp = F.R[1];  //根与当前最后一个节点互换 
		F.R[1] = F.R[i];
		F.R[i] = temp;
		Adjust(F, 1, i-1);  //互换后再建堆 
	} 
 } 

归并排序

//归并排序
void Tmerge(sqfile F, sqfile F1, int s, int m, int t)  //相邻两个子文件的归并算法 
{
	int i, j, k, r;
	i = s, j = m + 1;   //扫描指针初值 
	k = s;  //k为目标文件的记录指针 
	while((i < m) && (j <= t))
		if(F.R[i].key <= F.R[j].key)
		{
			F1.R[k] = F.R[i];   //R[i]送目标文件 
			i++; k++;
		}
		else
		{
			i = j; r = t;
		}
		if(i <= m) r = m;
		else
		{
			i = j;  //置剩余部分的起始序号 
			r = t;
		}
		while(i <= r)
		{
			F>R[k] = F.R[i];  //复制子文件的剩余部分 
			i++; k++;
		}
}

编程实现 O(n) 时间复杂度内找到一组数据的第 K 大元素

查找

实现一个有序数组的二分查找算法
实现模糊二分查找算法(比如大于等于给定值的第一个元素)

//二分查找
int Binsearch(sqlist r, keytype k)
{
	int low, high, mid;
	low = 1; high = r.len;
	while(low <= high)
	{
		mid = (low + high) / 2;
		if(k == r.data[mid].key) return(mid);
		if(k < r.data[mid].key) high = mid - 1;
		else low = mid + 1; 
	}
	return(0);
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值