廢話少說,直接上代碼
.h就不貼出來了 註解部分來自某博文 對理解很有協助,所以拿過來一下
#include "ArraySh.h"
#include <iostream>
using namespace std;
ArraySh::ArraySh(int size){
data = new long[size];
items = 0;
}
ArraySh::~ArraySh(){
delete data;
}
void ArraySh::insert(long d){
data[items++] = d;
//items++;
cout<<"insert num is :"<<d<<endl;
}
void ArraySh::Display(){
//int index = 0;
for(int i = 0;i < items;i++){
cout<<" data is :"<<data[i]<<endl;
}
}
long ArraySh::remove(int index){
long l = 0;
if(index < items){
l = data[index];
data[index] = NULL;
items--;
}
return l;
}
void ArraySh::shellSort(){
int h = 1;
while (h <= items/3)// 計算間隔h最大值
h = 3*h+1;
while (h > 0 )// 能否繼續通過縮小間隔h來分割資料列的判定
{
/* out為什麼從h開始?你分割後的第一子序列應該是這樣一個序列,0, h, 2h, 3h, ...
插入排序的while迴圈是從1開始的,因為第一個數始終有序,不需要比較,這個需要瞭解插入排序的演算法,所以比較是從第二個資料線,就是數組的第h個下標開始
out的判定為什麼是out < len?
控制數組下標,下面的例子會說道
下面舉一個例子來解釋
假定有一個10個資料項目的數組,數組下標從0 ~ 9 表示
當h = 4時的子序列情況是這樣的,以下標表示
(0 4 8)(1 5 9)(2 6)(3 7)
我第一次是這麼理解的,真對每一組分別進行插入排序(當然也可以這樣實現,但是下標不好控制),但是對下面的代碼來說這是錯誤的理解。
正確的過程是這樣的,外層for迴圈每次對每一分組的前兩個資料項目進行插入排序,然後前3個,然後前4個 ... 這個和子序列個數有關
排序過程只真對方括弧進行
當out = 4時進行如下過程 ([0 4] 8)
當out = 5時([1 5] 9)
當out = 6時([2 6])
當out = 7時([3 7])
當out = 8時([0 4 8])
當out = 9時([1 5 9])
h = 4執行完畢,然後h = (h - 1) / 3 = 1開始新的for迴圈
h = 1時執行過程和h = 4時一樣,不過這時的子數列就是原始的數列,蛻變為一個簡單的插入排序,這是數組基本有序,資料項目移動次數會大大減少*/
int inner = 0,outer = 0;
long temp;
for(outer = h;outer < items;outer++){// 外層通過out確定每組插入排序的第二個資料項目
// 以下代碼就是對子序列進行的插入排序演算法
inner = outer;
temp = data[outer];
/*
* 比較插入排序while迴圈的寫法,這裡的while迴圈與h有關,所以判定就與h有關,包括 in -= h語句
* while(in > 0 && array[in - 1] > tmp){
* array[in] = array[in - 1];
* in--;
* }
* array[in] = tmp;
*
*/
while (inner > h-1 && data[inner-h] > temp)
{
data[inner] = data[inner-h];
inner -= h;
}
data[inner] = temp;
}
h = (h-1)/3;
}
}
main方法所在檔案
#include <iostream>
#include <math.h>
#include "ArraySh.h"
using namespace std;
int main(void){
ArraySh as(10);
for (int i= 0;i < 10;i++)
{
int d = rand();
as.insert(d);
cout<<"rand num is:"<<d<<endl;
}
as.shellSort();
as.Display();
return 1;
}