严蔚敏数据结构习题10.30

这个快排的话,说实话,之前一直写的都是递归形式的快排,对待非递归的快排,也就是自己要维护一个栈,所以觉得挺有意义的,单开一个博文,记录一下。

先把我之前的递归形式的快排放上来,当然这个也是做了优化的快排,并没有每一次都把轴心元素和找到的元素交换,而是先通过low和high所指的元素之间的相互赋值,从而找到轴心元素应该所在的位置,从而直接一个赋值即可。

具体的步骤如下:

这里的话,将a[low]看作轴心元素,先用一个临时变量tmp保存数组a[low]的值,然后,从high侧开始比较,如果比tmp大,就移动high的指针,如果小的话,直接将这个值赋给low指针所指的值,low指针所指的第一个值是咱们的轴心元素,所以不用担心值的覆盖问题的。同样,low那边的元素也是同样的道理。代码如下:

#include<stdio.h>

//先写一个递归的快排算法

void printArray(int a[],int n);


int partition(int arr[],int low,int high)
{
	printf("%d %d\n", low,high);
	int aim;
	aim = arr[low];

	while(low < high)
	{
		while(low < high && arr[high] >= aim) --high; //先从high开始
		//直到while不满足循环的时候,即存在一个比中间值小的数,此时赋值过来,这里不用交换
		arr[low] = arr[high];	

		while(low < high && arr[low] <= aim) ++low;
		arr[high] = arr[low];

	}


	arr[low] = aim;

	return low;

}

void QSort(int arr[],int low,int high)
{
	if(low < high)
	{
		int middle;
		middle = partition(arr,low,high);
		printf("middle = %d\n",middle );
		QSort(arr,low,middle - 1);
		QSort(arr,middle + 1,high);
	}


}

void quicksort_firstq(int arr[],int n)
{
	QSort(arr,0,n-1);

}





void printArray(int a[],int n)
{
	int i;
	for(i = 0;i < n ; i++)
	{
		printf("%d ",a[i]);

	}

	printf("\n");

}


int main(int argc, char const *argv[])
{
	int a[8]={8,3,6,2,9,5,1,4};
	quicksort_firstq(a,8);

	printArray(a,8);
	
	return 0;
}

但是这道题目确是要求用非递归的方法,有点意思哦~
题目如下:
在这里插入图片描述

(1)

#include<stdio.h>

#define FALSE 0
#define TRUE 1


typedef struct 
{
	int low;
	int high;
	
}SNode;

int partition(int arr[],int low,int high)
{
	int aim;
	aim = arr[low];

	while(low < high)
	{
		while(low < high && arr[high] >= aim) --high; //先从high开始
		//直到while不满足循环的时候,即存在一个比中间值小的数,此时赋值过来,这里不用交换
		arr[low] = arr[high];	

		while(low < high && arr[low] <= aim) ++low;
		arr[high] = arr[low];

	}

	arr[low] = aim;

	return low;

}


void quicksort1(int arr[],int low,int high)
{
	int tag; //判断序列是否有序
	int position;   //轴心元素应该处的位置
	int lnum,rnum;  //左右子序列中元素的个数
	int count;      //栈中元素的个数
	SNode Stack[100]; //栈 0位置不用


	tag = TRUE;
	count = 0;

	while(tag)
	{
		position = partition(arr,low,high);
		if(position == low) //这里要判断是否是一个元素,如果是一个元素则有序,否则就需要进一步排序
		{
			if( (high-low) == 0)
				tag = FALSE;
			else
				low = low + 1;
		}
		if(tag)
		{
			lnum = position - low;
			rnum = high - position;

			if( lnum > 1 || rnum > 1)
			{
				count++;  

				if(lnum <= rnum) //左边的少,则先排左边的,将右边的上下界入栈
				{
					Stack[count].low = position+1;
					Stack[count].high = high;
					high = position - 1;  
				}

				else
				{
					Stack[count].low = low;
					Stack[count].high = position - 1;
					low = position + 1; //先排右边的
				}

			}//if( lnum > 1 || rnum > 1)
		}//if(tag)


		if(!tag || (lnum <= 1 && rnum <= 1))  //已经有序的时候
		{
			if(count)
			{
				low = Stack[count].low;  //将栈中保存的上下界弹出
				high = Stack[count].high;
				count --;  //出栈
				tag = TRUE;  //设定此时栈中无序
			}//if
		}//if

	}//while


}


void quicksort_1(int arr[],int n)
{
	quicksort1(arr,0,n-1);
}

void printArray(int a[],int n)
{
	int i;
	for(i = 0;i < n ; i++)
	{
		printf("%d ",a[i]);

	}

	printf("\n");

}


int main(int argc, char const *argv[])
{
	int a[8]={7,3,6,2,9,5,1,4};
	quicksort_1(a,8);

	printArray(a,8);
	
	return 0;
}

在这里插入图片描述

(2)

第二问,我们在排序之前先进行元素个数的检查

#include<stdio.h>

#define FALSE 0
#define TRUE 1

void printArray(int a[],int n);

//这样写并没有让记录小于3时用比较排序


typedef struct 
{
	int low;
	int high;
	
}SNode;

void swap(int *i,int *j)
{
	int p;
	p = *i;
	*i = *j;
	*j = p;
}

int partition(int arr[],int low,int high)
{
	int aim;
	aim = arr[low];

	while(low < high)
	{
		while(low < high && arr[high] >= aim) --high; //先从high开始
		//直到while不满足循环的时候,即存在一个比中间值小的数,此时赋值过来,这里不用交换
		arr[low] = arr[high];	

		while(low < high && arr[low] <= aim) ++low;
		arr[high] = arr[low];

	}

	arr[low] = aim;

	return low;

}


//这里我理解为冒泡排序吧
void compareSort(int arr[],int low,int high)
{
	int remark;
	int num = high - low + 1;
	do
	{
		remark = FALSE;
		for(int i = low; i < num - 1 ; i++)
		{

			if( arr[i] > arr[i+1] )
			{
				swap( &arr[i] , &arr[i+1] );
				remark = TRUE;

			}
		}

		num -- ;

	}while(remark);

}

void __quicksort2(int arr[],int low,int high)
{
	int tag = TRUE;  //判断序列是否有序
	SNode Stack[100];
	int lnum,rnum;
	int position;
	int i,j;
	int count = 0; //记录栈中元素,要初始一下元素

	while(1)//这里不是tag了
	{
		//先判断待排记录
		if(high - low + 1 <= 3)
		{
			compareSort(arr,low,high);
			//先判断栈里是否有元素,有就弹出
			if(count)
			{
				low = Stack[count].low;
				high = Stack[count].high;
				count --;
			}
			else
				break;
		}
		else
		{
			position = partition(arr,low,high);
			lnum = position - low;
			rnum = high - position;

			count++;

			if( lnum <= rnum ) //左边的元素少,右边入栈
			{
				Stack[count].low = position + 1;
				Stack[count].high = high;
				high = position - 1;
			}
			else
			{
				Stack[count].low = low;
				Stack[count].high = position - 1;
				low = position + 1;
			}


		}
	}
}

		

void quicksort2(int arr[],int n)
{
	__quicksort2(arr,0,n-1);

}
void printArray(int a[],int n)
{
	int i;
	for(i = 0;i < n ; i++)
	{
		printf("%d ",a[i]);

	}

	printf("\n");

}


int main(int argc, char const *argv[])
{
	int a[8]={7,3,6,2,9,5,1,4};
	quicksort2(a,8);

	printArray(a,8);
	
	return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
第1章 绪论 1.1 数据结构的基本概念和术语 1.1.1 引言 1.1.2 数据结构有关概念及术语 1.1.3 数据结构和抽象数据类型(ADT) 1.2 算法描述与分析 1.2.1 什么是算法 1.2.2 算法描述工具——C语言 1.2.3 算法分析技术初步 习题一 第2章 线性表 2.1 线性表的定义及其运算 2.1.1 线性表的定义 2.1.2 各种运算简介 2.2 线性表的顺序存储结构(向量) 2.2.1 顺序存储结构(向量) 2.2.2 向量中基本运算的实现 2.3 线性表的链表存储结构 2.3.1 单链表与指针 2.3.2 单链表的基本运算 2.4 循环链表和双向链表 2.4.1 循环链表 2.4.2 双向链表 2.4.3 顺序存储结构与链表存储结构的综合分析与比较 2.5 多项式相加问题 2.5.1 多项式相加的链表存储结构 2.5.2 多项式相加的算法实现 2.6 线性表的算法实现举例 2.6.1 实现线性表顺序存储结构及运算的C语言源程序 2.6.2 单链表处理的C语言源程序 习题二 第3章 栈和队列 3.1 栈 3.1.1 栈的定义及其运算 3.1.2 栈的顺序存储结构(向量) 3.1.3 栈的链表存储结构 3.1.4 栈的应用 3.2 队列 3.2.1 队列的定义及运算 3.2.2 队列的顺序存储结构(向量) 3.2.3 队列的链表存储结构 3.3 栈和队列的算法实现举例 习题三 第4章 串 4.1 串的基本概念 4.2 串的存储结构 4.2.1 串的顺序存储 4.2.2 串的链表存储 4.2.3 串变量的存储映象 4.3 串的运算 4.3.1 串的运算简介 4.3.2 串的匹配运算 4.4 文本编辑 习题四 第5章 数组和广义表 5.1 数组的基本概念 5.1.1 数组的概念 5.1.2 数组的顺序表示 5.1.3 特殊矩阵的压缩存储 5.2 稀疏矩阵的三元组存储 5.2.1 三元组表 5.2.2 稀疏矩阵的运算 5.3 稀疏矩阵的十字链表存储 5.3.1 十字链表的组成 5.3.2 十字链表的有关算法 5.4 广义表 5.4.1 广义表的概念和特性 5.4.2 广义表的存储结构 5.4.3 求广义表的深度 5.4.4 广义表的输出 5.4.5 建立广义表的存储结构 5.5 迷宫问题 习题五 第6章 树 6.1 树的基本概念和术语 6.1.1 树的定义 6.1.2 树的常用术语 6.1.3 树的表示方法 6.2 二叉树 6.2.1 二叉树的定义 6.2.2 二叉树的重要性质 6.2.3 二叉树的存储结构 6.2.4 二叉树二叉链表的一个生成算法 6.3 遍历二叉树 6.3.1 先根遍历 6.3.2 中根遍历 6.3.3 后根遍历 6.3.4 二叉树遍历算法的应用 6.4 线索二叉树 6.4.1 线索二叉树的基本概念 6.4.2 线索二叉树的逻辑表示图 6.4.3 中根次序线索化算法 6.4.4 在中根线索树上检索某结点的前趋或后继 6.4.5 在中根线索树上遍历二叉树 6.5 二叉树、 树和森林 6.5.1 树的存储结构 6.5.2 树与二叉树之间的转换 6.5.3 森林与二叉树的转换 6.5.4 一般树或森林的遍历 6.6 树的应用 6.6.1 二叉排序树 6.6.2 哈夫曼树及其应用 6.7 二叉树的建立和遍历C语言源程序示例 习题六 第7章 图 7.1 图的基本概念和术语 7.1.1 图的基本概念 7.1.2 路径和回路 7.1.3 连通图 7.1.4 顶点的度 7.2 图的存储结构 7.2.1 邻接矩阵 7.2.2 邻接链表 7.3 图的遍历和求图的连通分量 7.3.1 图的建立 7.3.2 图的遍历 7.3.3 求图的连通分量 7.4 图的生成树 7.4.1 生成树的概念 7.4.2 最小生成树 7.4.3 普里姆(Prim)算法和克鲁斯卡尔(Kruskal)算法 7.5 最短路径 7.5.1 单源顶点最短路径问题求解 7.5.2 求有向网中每对顶点间的路径 7.6 有向无环图及应用 7.6.1 拓扑排序 7.6.2 关键路径 7.7 图的算法C语言程序实现举例 7.7.1 无向图的邻接表的建立和遍历 7.7.2 有向无环图的拓扑排序和求关键路径 习题七 第8章 查找 8.1 基本概念
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

五月的天气

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

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

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

打赏作者

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

抵扣说明:

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

余额充值