【蓝蓝计算机考研算法】-day24-顺序表的删除重复、合并

197 阅读3分钟

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

思路

由于是有序的顺序表,值相同的元素一定在连续的位置上,采用双指针的方式:

  1. 从前往后遍历,使用两个指针i和j,其中i指向当前已处理好的无重复元素的最后一个位置,j指向当前待处理的元素位置。
  2. 如果当前元素L.data[j] 与前一个元素L.data[i]不相等,则将其移到前面,即将其放在i+1 的位置上,并将i指针向前移动一位。
  3. 最后修改顺序表的长度为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;
}

运行结果

image.png

复杂度

  • 时间复杂度 O(n)--- 遍历整个顺序表,其中n为顺序表表长
  • 空间复杂度O(1)--- 无额外存储空间,仅常熟级空间

36、将两个有序表合并成一个新的有序表。

思路

首先,按顺序不断取下两个顺序表表头较小的结点存入新的顺序表中。然后,看那个表还有剩余,将剩下的部分加到新的顺序表后面。
具体步骤:

  1. 创建两个有序的顺序表A和B
  2. 定义一个新的顺序表C存储合并后的数据
  3. 使用三个指针i,j,k分别指向有序表A、B、C的起始位置,其中i和J分别指向有序表A和B的第一个元素,K指向新的顺序表C的第一个位置。
  4. 依次比较有序表A和B中的元素,将较小的元素插入到有序表C中,具体操作是:若A.data[i] <= B.data[j],则将A.data[i]插入到C.data[k] 中,否则将B.data[j] 插入到 C.data[k] 中,然后将相应的指针向后移动一个位置。
  5. 循环执行步骤4,直到有序表A或B中的所有元素都被插入到有序表C中。
  6. 将剩余的有序表 A 或 B 中的元素插入到有序表 C 中。
  7. 设置新的有序顺序表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;
}

运行结果

image.png

复杂度

  • 时间复杂度 O(n+m)--- 遍历两个表,其中n、m分别为两个表表长
  • 空间复杂度 O(n+m)--- 辅助表的长度为n+m,其中n、m分别为两个表表长

小结

对于顺序表的创建问题还是没有解决,对某个方法有想法对写出来也还是很困难