Shell排序

接下来的几篇博客都是关于排序的;主要有插入类排序;交换类排序;选择类排序;

插入类排序主要有直接插入如排序(straight insertion sort);折半插入排序(bianry insertion sort); Shell sort;

交换类排序主要有冒泡排序(bubble sort); 快速排序(quick sort);

选择类排序主要有;简单选择排序(simple selection sort); 堆排序(heap sort);

除此之外还有归并排序(merge sort); 基数排序等;

本篇博客是关于Shell排序的;

排序直接的数据结构介绍;

            所有的排序均以线性表存储;所有的排序算法避免不了交换;交换就要用到临时变量;故将线性表中编号为0的元素不存储任何有效元素;仅仅当做临时变量或者记录的作用来使用;对于有些算法我会给出局部变量做临时变量的算法;若对线性表不是很了解;参见前面关于线性表的博客;

 

头文件(sort.h);

# ifndef _SORT_

typedef int KeyType;

typedef struct
{
	KeyType key;
}DataType;

# endif

头文件(SeqList.h);

typedef struct
{
	DataType data[MAXSIZE];
	int length;
}SeqList, * PSeqList;

//线性表排序基本准备;
PSeqList Init_SeqList(void);
bool Full_SeqList(PSeqList p);
int Push_SeqList(PSeqList p, KeyType keyValue);
void Traversal_SeqList(PSeqList p);
ostream & operator<<(ostream & os, DataType dataValue);

//基于线性表的排序方法;默认从小到大;
void StraightInsertSort(PSeqList p);
void BinaryInsertSort(PSeqList p);
void ShellInsert(PSeqList p, int gap);
void ShellSort(PSeqList p, int * gaps, int len);

实现文件(SeqList.cpp);

# include "SeqList.h"

PSeqList Init_SeqList(void)
{
	PSeqList p = (PSeqList)malloc(sizeof(SeqList));

	if (NULL != p)
	{
		p->length = 0;
		return p;
	}
	else
	{
		cout << "Memory allocate is error! " << endl;
		system("pause");
		exit(0);
	}
}


bool Full_SeqList(PSeqList p)
{
	if (p->length >= MAXSIZE)
	{
		return true;
	}
	else
	{
		return false;
	}
}

int Push_SeqList(PSeqList p, KeyType keyValue)
{
	if (Full_SeqList(p))
	{
		cout << "SeqList is full! " << endl;

		return -1;
	}

	p->data[p->length].key = keyValue;
	p->length++;

	return 0;
}

void Traversal_SeqList(PSeqList p)
{
	for (int i = 0; i < p->length; i++)
	{
		cout << p->data[i] << " ";
	}
	cout << endl;

	return;
}

ostream & operator<<(ostream & os, DataType dataValue)
{
	cout << dataValue.key;

	return os;
}

//基于线性表的排序方法;默认从小到大;

//直接插入排序;
void StraightInsertSort(PSeqList p)
{
	int i = 0;
	int j = 0;

	for (i = 2; i < p->length; i++)
	{
		//复制到前哨站;
		p->data[0] = p->data[i];

		j = i - 1;
		while (p->data[0].key < p->data[j].key)//必须是大于;不然不是稳定排序;
		{
			//移动元素;
			p->data[j + 1] = p->data[j];
			j--;
		}

		//元素最终移入正确位置;
		p->data[j + 1] = p->data[0];
	}

	return;
}

//折半插入排序;
void BinaryInsertSort(PSeqList p)
{
	int i = 0;
	int j = 0;
	int low = 0;
	int mid = 0;
	int high = 0;

	for (i = 2; i < p->length; i++)
	{
		//复制到前哨站;
		p->data[0] = p->data[i];

		//查找插入位置;
		low = 1;
		high = i - 1;
		while (low <= high)
		{
			mid = (low + high) / 2;

			if (p->data[0].key >= p->data[mid].key)//要么是大于等于要么是小于;即是相反;不然不是稳定排序;
			{
				low = mid + 1;
			}
			else
			{
				high = mid - 1;
			}
		}

		//移动元素腾出插入位置;这里high + 1为最终插入位置;
		for (j = i - 1; j >= high + 1; j--)
		{
			p->data[j + 1] = p->data[j];
		}

		//元素最终移入正确位置;
		p->data[j + 1] = p->data[0];
	}

	return;
}

//Shell插入;
void ShellInsert(PSeqList p, int gap)
{
	int i = 0;
	int j = 0;

	for (i = gap + i; i < p->length; i++)
	{
		if (p->data[i].key < p->data[i - gap].key)
		{
			p->data[0] = p->data[i];

			for (j = i - gap; (j > 0) && (p->data[0].key < p->data[j].key); j = j - gap)
			{
				p->data[j + gap] = p->data[j];
			}
			p->data[j + gap] = p->data[0];
		}
	}

	return;
}

//Shell排序;
void ShellSort(PSeqList p, int * gaps, int len)
{
	int i = 0;

	for (i = 0; i < len; i++)
	{
		ShellInsert(p, gaps[i]);
	}

	return;
}

主函数(Main.cpp);

# include "SeqList.h"

int main(int argc, char ** argv)
{
	cout << endl << endl << "----------------Shell test---------------" << endl;

	PSeqList pp = Init_SeqList();
	Push_SeqList(pp, 1);
	Push_SeqList(pp, 39);
	Push_SeqList(pp, 80);
	Push_SeqList(pp, 76);
	Push_SeqList(pp, 41);
	Push_SeqList(pp, 13);
	Push_SeqList(pp, 29);
	Push_SeqList(pp, 50);
	Push_SeqList(pp, 78);
	Push_SeqList(pp, 30);
	Push_SeqList(pp, 11);
	Push_SeqList(pp, 100);
	Push_SeqList(pp, 7);
	Push_SeqList(pp, 41);
	Push_SeqList(pp, 86);

	Traversal_SeqList(pp);
	cout << endl;

	int gaps[] = { 5, 3, 1 };
	ShellAllSort(pp, gaps, 3);

	Traversal_SeqList(pp);
	cout << endl;

	system("pause");
	return 0;
}

上面的算法只是对{ 1..........N}的元素进行排序;下面给出对{ 0.......N}的元素进行排序的算法;

分析;前面没有排序0号元素是因为0号元素被当做临时变量使用了,现在自定义一个临时变量代替它就可以了;

void ShellAllInsert(PSeqList p, int gap)
{
	int i = 0;
	int j = 0;
	DataType tem;

	for (i = gap; i < p->length; i++)
	{
		if (p->data[i].key < p->data[i - gap].key)
		{
			tem = p->data[i];

			for (j = i - gap; j >= 0 && tem.key < p->data[j].key; j = j - gap)
			{
				p->data[j + gap] = p->data[j];
			}
			p->data[j + gap] = tem;
		}
	}

	return;
}

void ShellAllSort(PSeqList p, int * gaps, int len)
{
	int i = 0;
	for (i = 0; i < len; i++)
	{
		ShellAllInsert(p, gaps[i]);
	}

	return;
}

 

<think>好的,我现在需要帮助用户解答如何在Shell中进行排序的问题。首先,用户提供的引用内容中有四个引用,都是关于排序算法的,特别是Shell中的实现。根据用户的问题,他可能想知道在Shell脚本中有哪些排序方法,或者如何使用内置命令如sort来进行排序。 首先,我需要回顾用户提供的引用内容。引用[1]和[4]提到了插入排序的Bash脚本实现,引用[3]描述了希尔排序的流程,而引用[2]则涉及使用sort命令进行多字段排序。用户的问题是如何在Shell中进行排序,可能包括手动实现排序算法和使用现有工具两种方法。 接下来,我需要确定用户的实际需求。如果是编写自定义排序算法,可能需要参考插入排序或希尔排序的例子。但更常见的情况是使用Shell内置的sort命令,因为手动实现排序算法在效率上不如使用现有工具。因此,回答应该涵盖这两个方面,但重点放在sort命令的使用上,因为它更为实用和高效。 然后,我需要整理引用中的信息。引用[2]详细说明了sort命令如何指定多个排序键,例如使用-k参数设置优先级。引用[1]和[4]提供了插入排序的Bash脚本,引用[3]描述了希尔排序的分组插入方法。这些可以作为手动实现排序算法的例子,但用户可能更关心如何快速有效地排序,因此需要强调sort命令的灵活性和功能。 在回答结构方面,应该先介绍sort命令的基本用法,然后展示示例,包括数值排序、多字段排序、逆序等。接着,如果需要自定义排序算法,可以简要提及插入排序和希尔排序的脚本,并说明它们的实现原理,但提醒用户这些方法效率较低,适合学习用途。 需要注意用户给出的引用中有关于插入排序和希尔排序的具体实现,所以在相关部分需要正确引用这些内容。例如,当提到插入排序时,引用[1]和[4]中的描述和代码可以作为示例;当讨论希尔排序时,引用[3]的分组方法需要被引用。 此外,用户要求生成相关问题,可能需要包括sort命令的高级用法、性能比较、自定义算法实现等。问题需要与回答内容相关,帮助用户进一步探索。 最后,要确保回答符合系统指令,正确使用LaTeX格式,所有行内数学表达式用$...$,独立公式用$$...$$,并且引用标识正确添加。同时,用中文回答,结构清晰,分步骤说明。</think>在Shell中进行排序主要有两种方式:使用内置的`sort`命令工具和手动实现排序算法。以下是具体方法及示例: --- ### 一、使用`sort`命令工具(推荐) `sort`是Shell中功能强大的文本排序工具,支持按字段、数据类型、逆序等规则排序。 #### 1. **基本语法** ```bash sort [选项] 文件名 ``` #### 2. **常用示例** - **数值排序**(按数值大小排序): ```bash echo "8 2 44 6 28 10" | tr ' ' '\n' | sort -n # 输出:2 6 8 10 28 44 ``` - **多字段排序**(先按第二列,再按第三列): ```bash echo -e "apple 3 5\nbanana 2 4\ncherry 3 6" | sort -k2,2n -k3,3n # 输出: # banana 2 4 # apple 3 5 # cherry 3 6 ``` - **逆序排序**: ```bash sort -r file.txt ``` #### 3. **复杂排序** - 指定分隔符(如按逗号分隔的CSV文件): ```bash sort -t',' -k2n data.csv ``` - 去重排序: ```bash sort -u file.txt ``` --- ### 二、手动实现排序算法(学习用途) #### 1. **插入排序** 引用[1]和[4]描述了插入排序的实现逻辑:逐个将元素插入已排序序列中。 示例Bash脚本: ```bash array=(8 2 9 44 6 28 10) length=${#array[@]} for ((i=1; i<length; i++)); do current=${array[i]} j=$((i-1)) while ((j >=0 && array[j] > current)); do array[j+1]=${array[j]} j=$((j-1)) done array[j+1]=$current done echo "排序后: ${array[@]}" # 输出: 2 6 8 9 10 28 44 [^1][^4] ``` #### 2. **希尔排序** 引用[3]提到希尔排序通过分组插入排序逐步缩小间隔实现高效排序: ```bash array=(8 2 9 44 6 28 10) length=${#array[@]} gap=$((length/2)) while ((gap > 0)); do for ((i=gap; i<length; i++)); do temp=${array[i]} j=$i while ((j >= gap && array[j-gap] > temp)); do array[j]=${array[j-gap]} j=$((j-gap)) done array[j]=$temp done gap=$((gap/2)) done echo "排序后: ${array[@]}" # 输出: 2 6 8 9 10 28 44 [^3] ``` --- ### 三、方法对比 | 方法 | 适用场景 | 性能 | |----------------|--------------------------|------------| | `sort`命令 | 大数据量、文件排序 | 高效稳定 | | 手动实现算法 | 学习算法原理、小数据量 | 较低效 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值