上篇文章已經提到直接插入排序中,時間消耗在了元素間的比較次數和移動這兩方面。折半插入排序可以減小比較次數,而表插入排序則可以避免元素移動。但它需要建立數據結構,並且需要額外的空間(省時一般都耗空間,這個在算法上很常見哦!)。
首先給出表結構,定義如下:
#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格式文件了,所以用數據銀行又發佈了一下,地址如下: