面試題22——編碼實現堆排,歸併排序,基數排序
阿新 • • 發佈:2018-12-09
堆排(大根堆):
void adjust(int*arr,int start,int end)
{
int tmp=arr[start];
for(int i=2*start+1;i<=end;i=2*i+1)
{
if(i<end&&arr[i]<arr[i+1])
{
i++;
}
if(arr[i]>tmp)
{
arr[start]=arr[i];
start=i;
}
else
{
break;
}
}
arr[start]=tmp;
}
void headpsort (int*arr,int len)
{
for(int i=(len-1-1)/2;i>=0;i--)
{
adjust(arr,i,len-1);
}
int tmp=0;
for(int i=0;i<len-1;++i)
{
tmp=arr[0];
arr[0]=arr[len-1-i];
arr[len-1-i]=tmp;
adjust(arr,0,len-1-i-1);
}
}
歸併排序:
void Merge(int *arr,int len,int gap)
{
int*brr=(int*)malloc(sizeof(int)*len);
assert(brr!=NULL);
int i=0;
//判斷 start1,end1,start2,end2 的位置
int s1=0;
int e1=s1+gap-1;
int s2=e1+1;
int e2=s2+gap-1<len-1?s2+gap-1:len-1;
//當有兩個歸併段時
while(s2<len)
{
//兩個歸併段都有資料
while((s1<=e1)&&(s2<=e2))
{
if(arr[s1]<=arr[s2])
{
brr[i++]=arr[s1++];
}
else
{
brr[i++]=arr[s2++];
}
}
//退出迴圈的兩種方式
while(s1<=e1)
{
brr[i++]=arr[s1++];
}
while(s2<=e2)
{
brr[i++]=arr[s2++];
}
s1=e2+1;
e1=s1+gap-1;
s2=e1+1;
e2=s2+gap-1<len-1?s2+gap-1:len-1;
}
//只有一個歸併段時
while(s1<len)
{
brr[i++]=arr[s1++];
}
for(int i=0;i<len;++i)
{
arr[i]=brr[i];
}
free(brr);
brr=NULL;
}
void Mergesort(int*arr,int len)
{
for(int i=1;i<len;i*=2)
{
Merge(arr,len,i);
}
}
基數排序:
//每個桶記憶體儲資料時相當於進行單鏈表的操作,建立單鏈表
typedef struct Node
{
int data;
struct Node*next;
}Node,*List;
//單鏈表的初始化
void InitList(List plist)
{
assert(plist!=NULL);
plist->next=NULL;
}
//新建一個結點
static Node*GetNode(int val)
{
Node*pGet=(Node*)malloc(sizeof(Node));
assert(pGet!=NULL);
pGet->data=val;
pGet->next=NULL;
return pGet;
}
//單鏈表的尾插,入桶
bool Insert(List plist,int val)
{
Node*p=plist;
while(plist->next!=NULL)
{
p=p->next;
}
Node*pGet=(Node*)malloc(sizeof(Node));
p-<next=pGet;
return true;
}
//刪除並儲存值,出桶操作
bool DelFirst(List plist,int*rtv)
{
Node*p=plist->next;
if(p==NULL)
{
return false;
}
*rtv=p->data;
plist->next=p->next;
free(p);
p=NULL;
return true;
}
//找出最大數並確定最大數的位數
int GetBitMax(int*arr,int len)
{
int max=arr[0];
int count=0;
for(int i=1;i<len;++i)
{
if(arr[i]>max)
{
max=arr[i];
}
}
while(max!=0)
{
count++;
max/=10;
}
return count;
}
//得到figure位上的數值
int Getnum(int num,int figure)
{
for(int j=0;j<figure;++j)
{
num=num/10;
}
return num%10;
}
void Base(int*arr,int len,int figure)
{
assert(arr!=NULL);
//建立桶
Node head[10];
for(int i=0;i<10;++i)
{
InitList(&head[i]);
}
int tmp;
for(int j=0;j<len;j++)
{
tmp=Getnum(arr[j],figure);
//得到 j 號下標 figure 位的數值
Insert(&head[tmp],arr[j]);
//入桶,遍歷陣列 figure 位相應的資料進入相應的桶裡
}
int n=0;
for(int j=0;j<10;)
{
if(DelFirst(&head[j],&arr[n]))
{
n++;
//j 號桶不一定只有一個數據,遍歷整個陣列用 n 代表一個桶裡存放資料的下表,
//避免出現多個數據使資料存放出現問題,覆蓋掉原先值或賦值後不改變
}
else
{
j++;
}
}
}
void Basesort(int*arr,int len)
{
int count=GetBitMax(arr,len);
for(int i=0;i<count;++i)
{
Base(arr,len,i);//i 表示當前數字從右往左數的位數
}
}