顺序表部分伪代码

本文探讨了关于顺序表的一系列算法问题,包括删除最小值元素、元素交换、逆序、选择排序、删除特定值、删除指定范围元素、查找与交换、循环左移、中位数计算以及主元素和最小未出现正整数的查找。所有算法均要求具有高效的时间和空间复杂度,并提供了C/C++/Java语言的实现思路和时间空间复杂度分析。
摘要由CSDN通过智能技术生成

顺序表部分伪代码

2、从顺序表中删除具有最小值的元素(假设唯一)并由函数返回被删元素。空出的位置由最后一个元素填补,若顺序表为空则显示出错信息并退出运行。

文字思想:
	typedef struct {
		ElemType data;
		int length;				// 代表顺序表的长度
	}SqList;
	1)判断顺序表长度是否为0,是则表示顺序表为空,显示出错信息退出
	2)用e接收待删除的元素,用L.data[L.length - 1]替换原先位置的元素,L.length减1
// 伪代码
void delMin(SqList &L,int pos,ElemType &value) {
    // 1) 判断顺序表是否为空
    if (L.length == 0) {
        return false;
    }
    // 调用最小值函数获取最小值及其对应的下标
    findMin(L,pos,value);
    L.data[pos] = L.data[L.length--];
    
    return true;
}

3、交换a、b元素值

文字思想:
	1)创建一个中间变量temp
	2)temp = a;a = b;b = temp;
// 伪代码
void swap(ElemType &a,ElemType &b) {
    ElemType temp = a;
    a = b;
    b = a;
}

4、设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)

文字思想:
	1) 判断顺序表L.length是奇数还是偶数,奇数则保持中间元素不动,其余元素首尾交换;偶数则是首尾元素两两交换
	2) 用于交换的swap函数的中间变量可以重复利用
则复杂度情况为:
	1)时间复杂度:O(n)
	2)空间复杂度:O(1)
// 伪代码
void reverse(SqList &L){
    if (L.length == 0){
        return false;			// 空表直接返回失败
    } else {
        int i;
        for (i = 0;i < L.length/2;i++){
            swap(L.data[i],L.data[L.length - 1 - i]);
        }
    }
}

5、用顺序表,实现简单选择排序

文字思想:
	1)从L.length个元素中选择值最小的元素,放到线性表的第一个位置,下一轮循环从剩下L.length - 1个元素中找到值最小的元素,以此类推,直到循环结束。
    2)每一轮找到最小值后和下标i位置处的元素交换位置
// 伪代码
void choice_sort(SqList &L) {
	int i,pos = 0,value = 0;
    for (i = 0;i < L.length;i++) {
        findMin(L,pos,value);				// 从无序顺序表中得到值最小元素下标及元素值
        swap(L.data[pos],L.data[i]);
    }
}

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

文字思想:
	1)逆序遍历,如果L.data[L.length-1]为x则直接删除且L.length -= 1
	2)若从后往前遍历到中间某部分出现x,则调用swap(L.data[i],L.data[L.length-1]),删除L.data[L.length-1],且令L.length -= 1
	3)直到条件不满足退出循环,则L.length代表非x元素个数
// 伪代码
void delx(SqList &L,int x) {
	int i;
    for (i = L.length - 1;i >= 0;i--) {
        // 最后一个元素恰好是x,直接指针向前移1个单元
        if (L.data[L.length - 1] == x) {
            L.length -= 1;			
        } else {
            // 在顺序表中间有x出现,和最后一个元素交换,再指针前移
            if (L.data[i] == x) {
                swap(L.data[i],L.data[L.length - 1]);
                L.length -= 1;
            }
        }
    }
}

7、从顺序表中删除位序位于i,j之间的所有元素

文字思想:
	1)取j = max(i,j),i = min(i,j);判断j - i大小,若j - i <= n - j,则从i到j开始遍历,使用swap(L.data[k],L.data[n-k+i-1]);最后L.length -= (j - i + 1);
	2)若j - i > n - j,则从j遍历到n,进行swap(L.data[k+1],L.data[k-j+i]),最后L.length -= (j - i +1)
void deli_to_j(SqList &L,int i,int j) {
	j = max(i,j);
    i = min(i,j);
    int k,n = L.length;
    if (j - i <= n - j) {
        for (k = i;k <= j;k++) {
            swap(L.data[k],L.data[n-k+i-1]);
        }
    } else {
        for (k = j;k <= n;k++) {
            swap(L.data[k+1],L.data[k-j+i]);
        }
    }
    L.length -= (j - i + 1);
}

8、找出有序顺序表中值在给定值s与t之间(要求s<t)的所有元素,返回下标范围

文字思想:
	1)常规思路是依次顺序遍历顺序表,找到首次大于s的元素下标及第一次大于t的元素下标,则范围已经确定,不过这种情况下时间复杂度为O(n),浪费了有序的特性
	2)可利用折半查找来确定,则时间复杂度为O(logn),但题目说是顺序表。。。
int range_tag(SqList L,ElemType s,ElemType t,int &start,int &end) {
    if (s >= t || L.length == 0) {
        return false;
    }
    // 寻找第一个大于s的元素下标
    int pos = -1,i,next = -1;
    for (i = 0;i < L.length;i++) {
        if (L.data[i] >= s) {
            pos = i;
        }
    }
    // 全表都比s小
    if (pos == -1) {
        return false;
    }
    // 寻找最后一个比t小的元素
    pos = max(pos,0);
    for (i = pos;i < L.length - 1;i++) {
        if (L.data[i] <= t) {
            next = i;
        }
    }
    start = pos;
    end = next;
    return true;
}

9、从有序顺序表中删除其值在给定值s与t之间(要求s<t)的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退出运行。

文字思想:
	1)判断L.length是否为0,是则表示顺序表为空,返回false,同时判断s>=t,是则返回false
	2)设置i为0,依次遍历顺序表,依次比较每个元素的值,若L.data[i]在s和t之间,赋值给L.data[k],k初始为0,则k+=1,直到遍历到最后一个元素,L.length = k,删除k后的元素
// 伪代码
bool dels2t(SqList &L,int t,int s) {
    if (L.length == 0 || s >= t) {
        return false;
    } else {
        int k = 0,i;
        for (i = 0;i < L.length;i++) {
            if (L.data[i] < t && L.data[i] > s) {
                L.data[k] = L.data[i];
                k += 1;
            }
        }
        L.length = k;
    	return true;
    }
}

10、从有序顺序表中删除所有值重复的元素,使表中所有元素的值均不同。

文字思想:
	例子:1,2,2,2,3,3,4——》1,2,3,4
	1)因为顺序表有序,则值相同的元素必定连续出现
	2)设置i从1开始遍历到L.length-1,k初始为1,若L.data[i] != L.data[i-1],L.data[k] = L.data[i];k += 1;
	3)遍历到最后k所指元素后面都是重复元素,L.length = k
bool delSameValue(SqList &L) {
    if (L.length <= 1) {
        return false;
    } else {
        int k = 1,i;
        for (i = 1;i < L.length;i++) {
            if (L.data[i] != L.data[i-1]) {
                L.data[k] = L.data[i];
                k += 1;
            }
        }
        L.length = k;
    	return true;
    }
}

或者思路2:

文字思想:
	1)将表划分为A表、B表;A表是该有序顺序表的前半部分,B表是该表的后半部分
	2)初始时,表A中只有一个元素,也就是有序顺序表的第一个元素,表B拥有剩下的n-1个元素;
	3)用表A的最后一个元素与表B从头开始比较,出现了不相等时,追加到表A尾巴上
	4)重复3)直到表B为空,再修改新表长为表A的长度(重复时表B接着上次比较的位置继续就行)
bool delSame(SqList &L) {
    // 表空,不存在,删除
    if (L.length == 0) {
        return false;
    } 
    // 在表A,B中进行索引的指针
    int indexA,indexB;
    for (indexA = 0,indexB = 1;indexB < L.length;indexB++) {
        if (L.data[indexA] != L.data[indexB]) {
            L.data[++indexA] = L.data[indexB];
        }
    }
    // 最终表长为表A的长度
    L.length = indexA + 1;
    return true;
}

11、将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。

文字思想:
	在归并排序那了解到最好的情况是前一个有序表的最后一个元素比后一个有序表的第一个元素还小,则此时比较次数为n,直接将第二个表拼接到第一个表的表尾。最坏情况是交叉,如:1,3,5,7和2,4,6,8则此时比较2n-1次
	1)两表表尾元素对其,比较输出值较大的元素到新表,输出元素后依旧保持表尾对其直到一个表为空
	2)将剩下的表中元素依次取出放到新表的表尾,则新表称为降序排列表
void addAB2C(SqList L1,SqList L2,SqList &L) {
    // 创建两个指针i,j分别指向两个表的表尾
    int i,j,k = 0;
    // 只要两表有一个为空则直接退出循环
    for (i = L1.length - 1,j = L2.length - 1;i >= 0 && j >= 0;) {
        if (L1.data[i] >= L2.data[j]) {
            L.data[k++] = L1.data[i--];
        } else {
            L.data[k++] = L2.data[j--];
        }
    }
    // 将剩余表中元素加入到L中
	if (i < 0) {
		for (i = j;i >= 0;i--) {
			L.data[k++] = L2.data[i];
		}
	} else {
		for (j = i;j >= 0;j--) {
			L.data[k++] = L1.data[j];
		}
	}
    L.length = k;
}

参考答案:从头开始进行比较

bool merge(SqList A,SqList B,SqList &C) {
    if (A.length + B.length < MaxSize) {
        return false;
    }
    // 分别索引表A,B,C
    int indexA = 0,indexB = 0,indexC = 0;
    // 有一个表处理完毕时,退出循环
    while (indexA < A.length && indexB < B.length) {
        // A表最左端
        if (A.data[indexA] <= B.data[indexB]) {
            C.data[indexC++] = A.data[indexA++];
        } else {
            C.data[indexC++] = B.data[indexB++];
        }
    }
    // 某个表还有剩余内容,直接追加到表C尾部
    while (indexA < A.length) {
        C.data[indexC++] = A.data[indexA++];
    }
    while (indexB < B.length) {
        C.data[indexC++] = B.data[indexB++];
    }
    // 设置表C的长度
    C.length = indexC;
    return true;
}

12、已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,a3,…,am)和(b1,b2,b3,…,bn)。试编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2,b3,…,bn)放在(a1,a2,a3,…,am)的前面。

文字思想:
	本题难点在于m和n大小情况未知
	1)m比n大时,例子:(1,2,3,4,5)(6,7,8)——》(6,7,8)(1,2,3,4,5);
	用暴力法还是比较简单的,可以另建一个新表存储,则空间复杂度为O(n),或者是将表往后移动n位,然后将(b1,b2……,bn)换到前面表中内容位空地方处
void swap(int &a,int b) {
    int c = a;
    a = b;
    b = c;
}
void exchange(SqList &L,int m,int n) {
    int x = L.length,i;
    // 线性表空间是已经申请过的,不能直接加长度 
    SqList T;
    T.length 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值