插入排序(二)— 表插入排序

上篇文章已經提到直接插入排序中,時間消耗在了元素間的比較次數和移動這兩方面。折半插入排序可以減小比較次數,而表插入排序則可以避免元素移動。但它需要建立數據結構,並且需要額外的空間(省時一般都耗空間,這個在算法上很常見哦!)。

首先給出表結構,定義如下:

#define SIZE 100

typedef struct
{
	int value;
	int next;
}SLNode;

typedef struct
{
	SLNode numbers[SIZE];
	int length;
}SLinkList;
其實,表結構就是一個靜態鏈表,它可以用一個數組來初始化,初始化用頭元素和第一個元素組成一個循環鏈表,然後排序時從第二個元素開始插入到這個循環鏈表中,當然只是修改每個元素的next域。使頭結點的next域始終指示最小的那個元素,然後依次向下:每一個元素的next域都指示比它稍大的那個元素。最大的元素的next域指示頭結點。這樣形成一個循環鏈表。

當記錄下這些信息後,最後一步就是按照next域的指示調整表結構中數組,得到最後的排序結構。下面分三步給出具體的代碼:

1、用數組初始化表結構。

2、修改next域形成有序的循環鏈表。

3、根據next域信息調整表結構中的數組,是數據從小到大排列。

最後再給出一個flash演示,因爲文章中不能插入.swf格式的文件,所以我給出鏈接和文件下載地址。這個動畫演示了表插入排序的整個過程。

一:用數組初始化表結構,代碼如下:

//參數含義: 
//values:存儲數據的整形數組
//count: 數組的大小
int InitLink(SLinkList* linkList,int* values,int count)
{
	if(count>=SIZE)
	{
		printf("超出範圍!\n");
		return 0;
	}
	//頭節點指示第一個元素,並賦予整形最大值(當然只要賦一個比你要排序的數都大的值就行了)
	linkList->numbers[0].value = INT_MAX;
	linkList->numbers[0].next = 1;

	for(int i=1;i<=count;i++)
	{
		linkList->numbers[i].value = values[i-1];
		linkList->numbers[i].next = 0;
	}
	linkList->length = count+1;
	return 1;
}

初始化後結構圖如下:



( 其中要排序的數組爲:int values[LENGTH] = {68,45,23,37,54,12,81,76};  LENGTH 爲宏定義是整數 8)

二、修改next域形成有序的循環鏈表。代碼如下:

int Sort(SLinkList* linkList)
{
	int len = linkList->length;
	for(int i=2;i<len;i++)
	{
		int q=0;
		int p = linkList->numbers[0].next;
		while( linkList->numbers[i].value > linkList->numbers[p].value )
		{
			q = p;
			p = linkList->numbers[p].next;
		}
		linkList->numbers[q].next = i;
		linkList->numbers[i].next = p;
	}
	return 1;
}

修改next域後如圖所示:


每一個元素的next域都指示下一個比它稍大的元素。

三、根據next域調整數組,使數組有序。代碼如下:

 // 根據靜態鏈表linkList中各結點的指針值調整記錄位置,使得linkList中記錄按關鍵字非遞減有序順序排列
void Arrange(SLinkList* linkList) 
{
	SLNode temp;
	int i,p,q;
	// p指示第一個記錄的當前位置
	p = linkList->numbers[0].next;  
	for (i=1; i<linkList->length; ++i) 
	{ 
		// 第i個記錄在linkList中的當前位置應不小於i
		// 找到第i個記錄,並用p指示其在linkList中當前位置
		while (p<i) 
		{
			p = linkList->numbers[p].next;
		}
		q = linkList->numbers[p].next; // q指示尚未調整的表尾
		if (p!= i) 
		{
			temp=linkList->numbers[p];
			linkList->numbers[p]=linkList->numbers[i];
			linkList->numbers[i]=temp;
			// 指向被移走的記錄,使得以後可由while循環找回
			linkList->numbers[i].next=p; 
		}
		 // p指示尚未調整的表尾,爲找第i+1個記錄作準備
		p=q;             
	}
} 

最後調整後結構如下圖:


最後:

一、該算法flash演示地址:

http://comic.sjtu.edu.cn/thucs/GD_jsj_002b/flash/chap10/10-2-4.swf

二:程序源文件及swf格式演示文件共享地址:

http://115.com/folder/fauqylsp#表插入排序

三、115網盤好像發佈不了swf格式文件了,所以用數據銀行又發佈了一下,地址如下:

http://dl.dbank.com/c0mbh4bf9v

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章