23王道数据结构数组章(1-14题)总结(伪代码)

本文介绍了顺序表的各种操作算法,包括删除最小值元素、顺序表逆置、删除指定值元素、有序表中删除指定范围元素、删除重复元素、合并有序表、顺序表位置互换、查找与交换、循环左移、找中位数、主元素查找及未出现最小正整数搜索。这些算法涉及数据结构和算法的基础知识,适用于C++或类似语法的编程语言。
摘要由CSDN通过智能技术生成

1.从顺序表中删除最小值元素(唯一)并由函数返回被删元素的值,空出的位置由最后一个元素填补,若顺序表为空,显示出错误信息并退出运行

算法思想:假设数组第一个元素为最小元素,再遍历数组元素与该元素比较,如果比该最小元素小,则更新最小元素值,并记录该最小元素值的位置

typedef struct{

    ElemType val[MaxSize];
    int length;
    
}SqList;

void Del_min(SqList &L,ElemType &value){//参数为引用型,用来返回值,因为会对原值修改
      
    if(L.length == 0){
        printf("数组为空");
    }
    
    ElemType min = L.val[0];
    
    int i,pos;//pos记录最小值元素的位置
    for(i = 1;i < L.length;i++){
        if(L.val[i] < min){
            min = L.val[i];
            pos=i;
        }
    }

    value = min;
    L.val[pos] = L.val[i-1];
    L.length--;
    
}

2.设计一个算法,将顺序表逆置,要求空间复杂度为o(1)

算法思想:双下标相向互换,单下标折半互换

//双下标相向互换
void Revese_L(SqList &L){

    int i = 0,j = L.length-1;
    while(i < j){
    
        ElemType temp = L.val[i];
        L.val[i] = L.val[j];
        L.val[j] = temp;

        i++;
        j--;

    }
   
}

//单下标折半互换
void Revese_L(SqList &L){

     int i = 0;
     while(i < L.length/2){
        
        ElemType temp = L.val[i];
        L.val[i] = L.val[L.length-1-i];
        L.val[L.length-1-i] = temp;

        i++;

    }

}

3.对长度为n的顺序表L,编写一个时间复杂度为o(n)、空间复杂度为o(1)的算法,该算法删除线性表中所有值为x的数据元素

算法思想:

①边扫描数组边记录下等于x的元素个数k,将不等于x的元素向前移动k各位置

②边扫描数组边记录不等于x的元素个数k,将不等于x的元素赋值在k下标下,并更新k值

//方式一
void Delete_x(SqList &L,ElemType x){

    int k = 0;//记录x的个数
    
    for(int i = 0;i < L.length;i++){

        if(L.val[i] == x){
            k++;
        }else{
            L.val[i-k] = L.val[i];
        }
    }
    
    L.length -= k;

}

//方式二
void Delete_x(SqList &L,ElemType x){

    int k = 0;//记录不等于x的元素个数
    
    for(int i = 0; i< L.length;i++){
        if(L.val[i] != x){
            L.val[k] = L.val[i];
            k++;
    }

    L.length = k;

}

4.从有序顺序表中删除其值在给定值s与t之间(s < t)的所有元素,若s或t不合理或顺序表为空,则显示错误信息并退出运行

算法思想:由于是有序表使以s与t之间的元素必连续存放,删除操作即从t(或大于t的第一个元素)的元素)起从s后第一个元素起开始覆盖

int Delete_s_t(SqList &L,ElemType s,ElemType t){

    if(L.length == 0 || s >= t){
        return 0;
    }

    //寻找s后的第一个元素位置
    int i = 0;

    while(i < L.length && L.val[i] <= s){
        i++;
    }
    
    if(i == L.length-1){
        return 0;
    }

    //寻找t或大于t的第一个元素所在位置
    int j = i;
    while(j < L.length && L.val[j] < t){
        j++;
    }

    //删除操作
    for(;j < L.length;j++,i++){

        L.val[i] = L.val[j];
        
    }

    L.length = i;

    return 1;

}

5.从顺序表中删除在给定值s与t间的元素(包括s和t)

算法思想:解法和代码类似于第3题


//方式一
int Delete_x(SqList &L,ElemType s,ElemType t){

    if(L.length == 0 || s >= t){
        return 0;
    }

    int k = 0;//记录在[s,t]上的元素个数
    
    for(int i = 0;i < L.length;i++){

        if(L.val[i] >= s && L.val[i] <= t){
            k++;
        }else{
            L.val[i-k] = L.val[i];
        }
    }
    
    L.length -= k;

    return 1;

}

//方式二
int Delete_x(SqList &L,ElemType x){

    if(L.length == 0 || s >= t){
        return 0;
    }

    int k = 0;//记录不在[s,t]上的元素个数
    
    for(int i = 0; i< L.length;i++){
        if(L.val[i] < s || L.val[i] > t){
            L.val[k] = L.val[i];
            k++;
    }

    L.length = k;
    return 1;

}

​

6.从有序顺序表中删除其值重复的元素,使表中元素各不相同

算法思想:由于有序顺序表,值重复的元素必定在一起,初始时将第一个元素归为非重复的有序表,从第二个元素起开始遍历,判断当前非重复有序表表尾元素是否与当前遍历元素相同,若相同,则继续向后遍历,若不同,将其插入非重复有序表的表尾

Void Delete_Common(SqList &L){
    
    for(int i = 0,j = 1;j < L.length;j++){
        if(L.val[i] != L.val[j]){//判断当前非重复有序表表尾元素是否与当前遍历元素相同
            L.val[++i] = L.val[j];//不同将该元素插入非重复有序表表尾
        }
    }

    L.length = i+1;
}

7.将两个有序表(设升序)合并成一个新的有序表,并由函数返回结果有序表

算法思想:同时遍历两个有序表,比较表中元素大小,将较小的赋值到结果表中,直至其中一个有序表遍历结束,再将未遍历完的有序表中的元素赋值到结果表中

bool merge(SqList L1,SqList L2,SqList &L){//L为结果表

    if(L1.length + L2.length > MaxSize){//MaxSize是定义的顺序表的最大长度
        
        return false;

    }
     
    int i = 0,j = 0,k = 0;

    while(i < L1.length && j < L2.length){
    
        if(L1.val[i] < L2.val[j]){

            L.val[k++] = L1.val[i++];

        }else{

            L.val[k++] = L2.val[j++];

        }

    }

    //将未遍历完的顺序表赋值到结果表中
    while(i < L1.length){
        L.val[k++] = L1.val[i++];
    }

    while(j < L2.length){
        L.val[k++] = L2.val[j++];
    }
    
    C.length = k;
    return true;
}

8.一维数组A[m + n]中存放两个线性表(a1,a2,a3,...am)和(b1,b2,b3,...,bn),试编写算法将数组

里的两个顺序表位置互换

算法思想:先将两个线性表各自反转,再对整个数组反转

void Revese(EmleType A[],int left,int right,int ArraySize){
    
    if(left >= right || right >= ArraySize || left < 0){
        return;
    }

    while(left < right){//双下标相向互换逆置

        EmleType temp = A[left];
        A[left] = A[right];
        A[right] = temp;

        left++;
        right--;
    }

}

void ExchangePos(ElemType A[],int m,int n,int ArraySize){

    Revese(A,0,m-1,ArraySize);
    Revese(A,m,m+n-1,ArraySize);
    Revese(0,m+n-1,ArraySize);

}

9.线性表(a1,a2,a3,...,an)中的元素递增有序且按顺序存储在计算机内,设计一个算法完成用最少时间在表中查找数值为x的元素,若找到,则将其与后继元素位置交换,若找不到,则将其插入表中使表中元素递增有序 

算法思想:顺序表且有序用折半查找时间复杂度最低,为O(log2n)

注意:将折半查找算法写在主函数中,其查找失败时的插入位置一定是high+1,即low所在位置

//折半查找
int Binary_Search(SqList L,Elemtype x){

    int low = 0,high = L.length-1;

    while(low <= high){

        int mid = (low + high)/2;
        
        if(L.val[mid] == x){
            return mid;//查找成功,返回其数组下标
        }else if(L.val[mid] > x){
            high = mid-1;
        }else{
            low = mid+1;
        } 
    }

    return -1;//查找失败,返回-1
}

void SearchExchangeInsert(SqList &L,Elemtype x){

    int index = Binary_Search(L,x);

    if(index != -1 && index != L.length-1){//查找成功且不是最后一个元素,与后继元素交换位置
        
        ElemType temp = L.val[index];
        L.val[index] = L.val[index+1];
        L.val[index+1] = temp;

    }else{//查找失败,插入并使其递增有序
        
        //寻找插入位置
        int i = 0;    
        while(L.val[i] <= x) i++;
        
        for(int j = L.length-1;j >= i;j--){
            L.val[j+1] = L.val[j];
        }
        
        L.val[i] = x;
        
    }    

}

10.设将n(n > 1)个整数存放到一维数组R中,设计一个在时间和空间两方面都尽可能高效的算法将R中保存的序列循环左移

算法思想:解法和代码同第8题,将0-p-1位置和p-n-1位置看作两个线性表分别逆置,再整体对数组逆置

11.找两个等长升序序列的中位数

算法思想:

12.找出一维整数数组的主元素;主元素:其元素个数大于数组长度的一半

算法思想:Boyer-Moore 投票算法

count初值为0,遍历数组

①先判断,当count初值为0时,将当前元素赋值给候选主元素candidate

②继续遍历,当数组元素等于candidate时count加1,否则count减一

遍历结束后,当count大于0时,candidate即为主元素,否则不存在主元素

int SearchMainElem(ElemType A[],int ArraySize){

    int count = 0,candidate;

    for(int i = 0;i < ArraySize;i++){

        if(count == 0){
            
            candidate = A[i];
        }

        count += A[i] == candidate ? 1 : -1;
        
    }

    if(count > 0){

       return candidate;
    
    }

    return -1;

}

13.找出长度为n的一维整型数组的未出现的最小正整数,且数组元素的大小<=n

算法思想:由于数组元素的大小<=n,且要求找最小正整数,故申请一个长度为n的数组空间当作存在标记数组,将原数组的正整数(1-n)当作该存在标记数组的数组下标,遍历原数组,将其数组值设置1当作存在标记,再遍历存在标记数组,第一个为0的数组元素的下标+1即为原数组中未出现的最小正整数

int Seach_Min(int nums[],int n){

    //创建并初始化存在标记数组
    int* arr = (int*)malloc(sizeof(int)*n);
    for(int i = 0;i < n;i++){
        arr[i] = 0;
    }
    
    //将原数组中的正整数设置存在标记
    for(int i = 0;i < n;i++){
        if(nums[i] > 0 && arr[nums[i]-1] != 1){
            arr[nums[i]-1] = 1;//设置为1,代表原数组中存在该元素
        }
    }
    //遍历存在标记数组,找到第一个元素值为0的数组下标
    int target = 0;
    for(int i = 0;i < n;i++){
        if(!arr[i]){
            target = i;
            break;
       }
    }

    return target+1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值