索引排序

索引排序

在排序时,若是数据非常复杂。对数据的移动显然是费时的。若把数据移动改为索引(或指针)移动。则降低了操作复杂度。索引排序。也叫地址排序,就是这样的排序思想。

索引含义

依据索引的含义不同,索引排序的算法上也主要分为两种。

一、index[i]为array[i]终于在有序序列中的位置。

二、index[i]为位置i上终于应存放元素的下标。即终于元素按array[index[0]]、array[index[1]]……有序。

一个实例

原序列 array: 17  19  23  21  38  5   33  22

        下标:0   1   2   3   4   5   6   7

      index1:1   2   5   3   7   0   6   4

      index2:5   0   1   3   7   2   6   4

得到索引数组后,依据索引数组对元素进行重排,因为index含义不同,重排算法也不同。以下直接给出两种索引排序代码,代码中有具体凝视:

索引排序一

代码

#include<iostream>
#include<iomanip>
using namespace std;
/*
索引排序一
index[i]是array[i]的终于下标
*/
void IndexSort1(int array[], int n)
{
	if (array && n > 1)
	{
		//创建索引数组
		int *index = new int[n];
		//初始化索引数组
		int i, j;
		for (i = 0; i < n; i++)
			index[i] = i;
		//相似于插入排序。在插入比較的过程中不断地改动index数组
		for (i = 1; i < n; i++)
		{
			j = i;
			while (j)
			{
				if (array[i] < array[j-1])
				{
					index[i]--;
					index[j - 1]++;
				}
				j--;
			}
		}
		//打印索引数组
		cout << "索引数组" << endl;
		for (i = 0; i < n; i++)
			cout << setw(4) << index[i];
		cout << endl;
		//依据index数组。重排原序列
		bool modified = true;
		while (modified)
		{
			modified = false;
			for (i = 0; i < n - 1; i++)
			{
				//假设不在位置上,则调整
				if (index[i] != i)
				{
					modified = true;
					j = index[i];
					swap(array[i], array[j]);
					index[i] = index[j];
					index[j] = j;
				}
			}
		}
		//释放空间
		delete[]index;
	}
}

//打印
void print(int array[], int n)
{
	if(array && n>0)
	{
		int i;
		for (i = 0; i < n; i++)
			cout << setw(4) << array[i];
		cout << endl;
	}
}
int main()
{
	cout << "***索引排序***by David***\n";
	int array[] = {17, 19, 23, 21, 38, 5, 33, 22};
	int n = sizeof(array) / sizeof(array[0]);
	cout << "原序列\n";
	print(array, n);
	cout << "索引排序一" << endl;
	IndexSort1(array, n);
	cout << "排序后" << endl;
	print(array, n);
	system("pause");
	return 0;
}

执行


 

索引排序二

代码

#include<iostream>
#include<iomanip>
using namespace std;
/*
索引排序二
index[i]是array[i]中应该放置数据的下标
*/
void IndexSort2(int array[], int n)
{
	if (array && n > 1)
	{
		//创建索引数组
		int *index = new int[n];
		//初始化索引数组
		int i, j;
		for (i = 0; i < n; i++)
			index[i] = i;
		//相似于插入排序,在插入比較的过程中不断地改动index数组
		for (i = 0; i < n; i++)
		{
			j = i;
			while (j)
			{
				if (array[index[j]] < array[index[j - 1]])
					swap(index[j], index[j - 1]);
				else
					break;
				j--;
			}
		}
		//打印索引数组
		cout << "索引数组" << endl;
		for (i = 0; i < n; i++)
			cout << setw(4) << index[i];
		cout << endl;
		//元素重排
		int temp, k;
		for (i = 0; i < n; i++)
		{
			j = i;
			temp = array[i];
			while (index[j] != i)
			{
				k = index[j];
				array[j] = array[k];
				index[j] = j;
				j = k;
			}
			array[j] = temp;
			index[j] = j;
		}
		//释放空间
		delete[]index;
	}
}

//打印
void print(int array[], int n)
{
	if(array && n>0)
	{
		int i;
		for (i = 0; i < n; i++)
			cout << setw(4) << array[i];
		cout << endl;
	}
}
int main()
{
	cout << "***索引排序***by David***\n";
	int array[] = {17, 19, 23, 21, 38, 5, 33, 22};
	int n = sizeof(array) / sizeof(array[0]);
	cout << "原序列\n";
	print(array, n);
	cout << "索引排序二" << endl;
	IndexSort2(array, n);
	cout << "排序后" << endl;
	print(array, n);
	system("pause");
	return 0;
}

元素重排算法的详解

/*
元素重排
看似两重循环,则实际上的时间复杂度是线性的:O(n)
普通情况下。经过一次while循环,将有多个元素归位
*/
int temp, k;
for (i = 0; i < n; i++)
{
	/*
	加了这个推断后,while循环的后两条语句的运行得到优化
	:当元素已在正确的位置,则不需回填
	*/
      if (index[i] != i)
	{
		//下面的做法相似于“挖坑填数”
		j = i;
		temp = array[i];
		while (index[j] != i)
		{
			k = index[j];
			//元素归位
			array[j] = array[k];
			//索引归位
			index[j] = j;
			//新的坑
			j = k;
		}
		//元素归位
		array[j] = temp;
		//索引归位
		index[j] = j;
	}
}

执行


    

转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/37889669


若有所帮助。顶一个哦。


专栏文件夹:


posted @ 2017-04-29 11:49  zhchoutai  阅读(3730)  评论(0编辑  收藏  举报