上篇文章已經提到直接插入排序中,時間消耗在了元素間的比較次數和移動這兩方面。折半插入排序可以減小比較次數,而表插入排序則可以避免元素移動。但它需要建立資料結構,並且需要額外的空間(省時一般都耗空間,這個在演算法上很常見哦!)。
首先給出表結構,定義如下:
#define size 100
typedef struct
slnode;
typedef struct
slinklist;
其實,表結構就是乙個靜態鍊錶,它可以用乙個陣列來初始化,初始化用頭元素和第乙個元素組成乙個迴圈鍊錶,然後排序時從第二個元素開始插入到這個迴圈鍊錶中,當然只是修改每個元素的next域。使頭結點的next域始終指示最小的那個元素,然後依次向下:每乙個元素的next域都指示比它稍大的那個元素。最大的元素的next域指示頭結點。這樣形成乙個迴圈鍊錶。
當記錄下這些資訊後,最後一步就是按照next域的指示調整表結構中陣列,得到最後的排序結構。下面分三步給出具體的**:
1、用陣列初始化表結構。
2、修改next域形成有序的迴圈鍊錶。
3、根據next域資訊調整表結構中的陣列,是資料從小到大排列。 一:
用陣列初始化表結構,**如下:
//引數含義:
//values:儲存資料的整形陣列
//count: 陣列的大小
int initlink(slinklist* linklist,int* values,int count)
//頭節點指示第乙個元素,並賦予整形最大值(當然只要賦乙個比你要排序的數都大的值就行了)
linklist->numbers[0].value = int_max;
linklist->numbers[0].next = 1;
for(int i=1;i<=count;i++)
linklist->length = count+1;
return 1;
}
初始化後結構圖如下:
( 其中要排序的陣列為:int values[length] = ; length 為巨集定義是整數 8) 二、
修改next域形成有序的迴圈鍊錶。**如下:
int sort(slinklist* linklist)
linklist->numbers[q].next = i;
linklist->numbers[i].next = p;
} return 1;
}
修改next域後如圖所示:
每乙個元素的next域都指示下乙個比它稍大的元素。
三、根據next域調整陣列,使陣列有序。**如下:
// 根據靜態鍊錶linklist中各結點的指標值調整記錄位置,使得linklist中記錄按關鍵字非遞減有序順序排列
void arrange(slinklist* linklist)
q = linklist->numbers[p].next; // q指示尚未調整的表尾
if (p!= i)
// p指示尚未調整的表尾,為找第i+1個記錄作準備
p=q;
}}
最後調整後結構如下圖:
最後:
表插入排序
插入排序 簡單插入排序 二分插入排序
1 假設我們手裡的數字是一堆亂序撲克牌,我們想把它整理成從小到大的排序,會怎麼辦呢,我們會從左往右挨個將牌抽出來插到它合適的位置,這樣一輪之後,就變成從小到大的順序了。2 程式上怎麼實現,從第二位開始,逐個將後乙個數和它之前所有的資料進行比較,尋找這個數最合適的插入位置,將其插入空隙,後面的值依次會...
插入排序 折半插入排序
折半插入排序 binary insertion sort 直接插入排序採用順序查詢法查詢當前記錄在已排好序的序列中插入位置,這個 查詢 操作可利用 折半查詢 來實 現,由此進行的插入排序稱之為折半插入排序 binary insertion sort 演算法思想 1 將待排序的記錄存放在陣列r 1.n...
插入排序 折半插入排序
折半插入排序是基於直接插入排序的優化。直接插入排序 將第i個元素插入時,通過折半查詢的方式,來查詢第i個元素合適的位置。當0 i 1 位置上的元素都已經排序ok,現需要插入第i個元素,設其值為temp 令low 0,high i,mid high low 2。那麼temp可能插入的位置是 low h...