題目
編寫一個函數,利用二分查找算法在一個有序表中插入一個關鍵字k,並保持表的有序性。
分析
先在有序表中利用二分查找算法查找關鍵字值等於或小於k的結點,m指向正好等於k的結點或l指向關鍵字正好大於k的結點,然後採用移動法插入k結點即可。
本題的難點就是如何利用二分查找算法找到合適的插入位置。
有兩種情況:第一種是有序表中沒有等於關鍵字k的結點,尋找大於k的結點即可;第二種是有序表中存在等於關鍵字k的結點,尋找等於k的結點即可。
圖解如下:
將兩種情況用同一部分代碼來處理,定義一個標誌位變量flag,用來記錄是否有等於關鍵字k的情況,初始爲0表示沒有等於關鍵字k的情況,如果有則將flag置爲1,然後退出循環,最終根據標誌位flag來判斷插入位置。
代碼
核心代碼:
/* 使用二分查找在順序表中插入元素k */
void insertK(int nums[],int n,int k){
int mid;// 記錄中間下標
int low=0,high=n-1;
int flag=0;// 標誌,用來記錄是否有等於k的值
int pos;// 定義的變量,爲插入的位置
while(low<=high&&flag==0){// 循環當low>high時跳出循環
mid=(low+high)/2;
if(nums[mid]==k){
flag=1;// 如果發現有關鍵字等於k,則將標誌flag置爲1,退出循環然後插入k
}else if(nums[mid]>k){
high=mid-1;
}else if(nums[mid]<k){
low=mid+1;
}
}
/* 確定插入位置 */
if(flag==1){// 如果flag爲1則發現序列中有關鍵字等於k,則使插入位置等於mid
pos=mid;
}else{// 如果flag爲0則表示序列中沒有與關鍵字k相等的值,則插入位置爲low
pos=low;
}
/* 插入關鍵字k */
for(int i=n-1;i>=pos;i--){
nums[i+1]=nums[i];
}
nums[pos]=k;
}
完整代碼如下:
#include<stdio.h>
/* 打印數組 */
void printArr(int nums[],int n){
printf("\n");
for(int i=0;i<n;i++){
printf("%d\t",nums[i]);
}
printf("\n");
}
/* 使用二分查找在順序表中插入元素k */
void insertK(int nums[],int n,int k){
int mid;// 記錄中間下標
int low=0,high=n-1;
int flag=0;// 標誌,用來記錄是否有等於k的值
int pos;// 定義的變量,爲插入的位置
while(low<=high&&flag==0){// 循環當low>high時跳出循環
mid=(low+high)/2;
if(nums[mid]==k){
flag=1;// 如果發現有關鍵字等於k,則將標誌flag置爲1,退出循環然後插入k
}else if(nums[mid]>k){
high=mid-1;
}else if(nums[mid]<k){
low=mid+1;
}
}
/* 確定插入位置 */
if(flag==1){// 如果flag爲1則發現序列中有關鍵字等於k,則使插入位置等於mid
pos=mid;
}else{// 如果flag爲0則表示序列中沒有與關鍵字k相等的值,則插入位置爲low
pos=low;
}
/* 插入關鍵字k */
for(int i=n-1;i>=pos;i--){
nums[i+1]=nums[i];
}
nums[pos]=k;
}
int main(){
int nums[]={1,2,3,4,5,6,7};
int n=7;
int k=5;
insertK(nums,n,k);// 插入k
printArr(nums,n);// 打印數組
return 0;
}
運行結果: