35、从有序顺序表中删除所有其值重复的元素,使表中元素不重复。
思路
由于是有序的顺序表,值相同的元素一定在连续的位置上,采用双指针的方式:
- 从前往后遍历,使用两个指针i和j,其中i指向当前已处理好的无重复元素的最后一个位置,j指向当前待处理的元素位置。
- 如果当前元素L.data[j] 与前一个元素L.data[i]不相等,则将其移到前面,即将其放在i+1 的位置上,并将i指针向前移动一位。
- 最后修改顺序表的长度为i+1,即为去重后的元素个数。
具体实现
//删除顺序表中重复元素
#include<stdio.h>
#define MAXSIZE 100 //定义顺序表的最大长度
typedef struct {
int data[MAXSIZE]; //顺序表的元素
int length; //顺序表当前的长度
}SqList;
//创建顺序表
bool CreateList(SqList& L, int n) {//创建有n个元素的顺序表
if (n > MAXSIZE) return false;
for (int i = 0; i < n; i++) {
scanf_s("%d", &L.data[i]);
}
L.length = n; //更新顺序表的长度
return true;
}
//怎么不指定个数的时候,会实现不了,无法创建成功
//bool CreateList(SqList& L) {
// int i = 0;
// while (scanf_s("%d",&L.data[i++]))
// {
// L.length++; //表长加一
// if (getchar() == '\n') {//输入换行 就结束
// break;
// }
// }
// if (L.length > MAXSIZE) {//表长大于定义的最大长度
// return false;
// }
// else{
// printf("创建成功\n ");
// return true;
// }
//
//}
//函数功能:从有序顺序表中删除所有重复元素,使表中元素不重复
bool Delete_SameList(SqList& L) {
if (L.length == 0)
return false;
int i, j; //i存储第一个不相同的元素,j为工作指针
for (i = 0, j = 1; j < L.length; j++) {
if (L.data[j] != L.data[i]) { //如果当前元素与前一个元素不相等,则将其移道前面
i++; //i指针指向下一个位置
L.data[i] = L.data[j]; //当前元素移动到前面
}
}
L.length = i + 1;//i是从-开始,所以长度为i+1
return true;
}
int main() {
SqList L; //初始化有序的顺序表
int n;
printf("请输入顺序表的长度,不要超过最大长度:");
scanf_s("%d", &n);
printf("请输入%d个元素的值:", n);
CreateList(L,n); //创建顺序表
printf("删除重复后的顺序表:");
Delete_SameList(L);//删除顺序表重复值
//输出删除重复后的顺序表
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
return 0;
}
运行结果
复杂度
- 时间复杂度 O(n)--- 遍历整个顺序表,其中n为顺序表表长
- 空间复杂度O(1)--- 无额外存储空间,仅常熟级空间
36、将两个有序表合并成一个新的有序表。
思路
首先,按顺序不断取下两个顺序表表头较小的结点存入新的顺序表中。然后,看那个表还有剩余,将剩下的部分加到新的顺序表后面。
具体步骤:
- 创建两个有序的顺序表A和B
- 定义一个新的顺序表C存储合并后的数据
- 使用三个指针i,j,k分别指向有序表A、B、C的起始位置,其中i和J分别指向有序表A和B的第一个元素,K指向新的顺序表C的第一个位置。
- 依次比较有序表A和B中的元素,将较小的元素插入到有序表C中,具体操作是:若A.data[i] <= B.data[j],则将A.data[i]插入到C.data[k] 中,否则将B.data[j] 插入到 C.data[k] 中,然后将相应的指针向后移动一个位置。
- 循环执行步骤4,直到有序表A或B中的所有元素都被插入到有序表C中。
- 将剩余的有序表 A 或 B 中的元素插入到有序表 C 中。
- 设置新的有序顺序表C的长度为 k,即为合并后的有序表的长度
注意点:将剩余的有序表 A 或 B 中的元素插入到有序表 C 中,此时两个while循环只会执行其中一个,因为初次比较的时候已经将其中一个表中所有元素插入到表C中。
具体实现
#include<stdio.h>
#define MAXSIZE 100 //定义顺序表的最大长度
typedef struct {
int data[MAXSIZE]; //顺序表的元素
int length; //顺序表当前的长度
}SqList;
//创建顺序表
bool CreateList(SqList& L, int n) {//创建有n个元素的顺序表
if (n > MAXSIZE) return false;
for (int i = 0; i < n; i++) {
scanf_s("%d", &L.data[i]);
}
L.length = n; //更新顺序表的长度
return true;
}
//将两个顺序表合并为一个新的顺序表
SqList Merge(SqList A, SqList B) {
SqList C; //定义新的顺序表C
int i = 0, j = 0,k = 0;// i、j、k分别指向表A、B、C
//if (A.length + B.length > C.length) {//不符合的时候
// return ;
//}
// 将A和B中较小的元素放入C中
while (i<A.length&&j<B.length)
{
if (A.data[i] <= B.data[j]) {
C.data[k++] = A.data[i++];
}
else {
C.data[k++] = B.data[j++];
}
}
// 将A和B中剩余的元素放入C中
while (i<A.length)
{
C.data[k++] = A.data[i++];
}while (j < B.length)
{
C.data[k++] = B.data[j++];
}
C.length = k; // 设置新的有序顺序表C的长度
return C;
}
int main() {
SqList A; //初始化有序的顺序表A
SqList B; //初始化有序的顺序表B
int a,b;
printf("请输入顺序表A的长度,不要超过最大长度:");
scanf_s("%d", &a);
printf("请输入%d个元素的值:", a);
CreateList(A,a); //创建顺序表A
printf("请输入顺序表A的长度,不要超过最大长度:");
scanf_s("%d", &b);
printf("请输入%d个元素的值:", b);
CreateList(B, b); //创建顺序表B
printf("合并后的顺序表:");
SqList C = Merge(A, B);// 合并A和B为新的有序顺序表C
//输出删除重复后的顺序表
for (int i = 0; i < C.length; i++) {
printf("%d ", C.data[i]);
}
return 0;
}
运行结果
复杂度
- 时间复杂度 O(n+m)--- 遍历两个表,其中n、m分别为两个表表长
- 空间复杂度 O(n+m)--- 辅助表的长度为n+m,其中n、m分别为两个表表长
小结
对于顺序表的创建问题还是没有解决,对某个方法有想法对写出来也还是很困难