408 顺序表代码题

347 阅读4分钟

408 数据结构

顺序表代码题

我目前写的这些题基本上都是冲刺必会代码100题里面的,后续应该会补充在写王道大题时遇到的一些真题和好题。

一些函数还有传参时用到的函数我没有在这篇文章中写,有需要的可以复制一下我上一篇文章的代码。

1 已知线性表(a1 a2 ----an)按顺序结构存储且每个元素为不相等的整数。设计把所有奇数挪到所有偶数前面的算法。(要求时间最少 辅助空间最少)

void Moveodd(seqlist* L)
{
	//前后相互遍历的思想
	int i = 0, j = L->length - 1;
	ElementType temp;
	while (i <= j)
	{
		//奇数
		if (L->data[i] % 2 == 1)
			i++;
		//偶数在后面
		if (L->data[j] % 2 == 0)
			j--;
		if (L->data[i] % 2 == 0 && L->data[j] % 2 == 1)
		{
			temp = L->data[j];
			L->data[j] = L->data[i];
			L->data[i] = temp;
			i++;
			j--;
		}
	}

}

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

void Reverse(seqlist* L)
{
	ElementType temp;
	//如果L->length 长度 为8 的话 占用了0-7  数字下标小宇 这个4即可 0123 前面四个和后面四个对比
	// 长度为9 0-8 小于4 0123 4 5678 前四个和后四个交换位置 中间这个不动
	for (int i = 0; i < (L->length) / 2; i++)
	{
		temp = L->data[i];
		L->data[i] = L->data[L->length - 1 - i];
		L->data[L->length - 1 - i] = temp;
	}
}

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

image-20220330212922786.png

void Merge(seqlist* L, seqlist* X,seqlist* C)
{
	//两个表都是有序表 对比他俩的第一个元素 谁小谁先放前面。
	int i = 0;
	int j = 0;
	int k = 0;
	//怎么说呢 得先比较这个length吧 要是length加一起超过了最大长度 那肯定不能合并了
	if (L->length + X->length > List_size)
	{
		printf("这两个顺序表的长度加起来大于最大长度! 无法合并");
	}
	//任何一个顺序表要是对比完了 他就不能接着在这里面比较了 他用完了 对面的就全接在后面了
	while (i < L->length && j < X->length)
	{
		//比大小 小的放前面
		if (L->data[i] < X->data[j])
		{
			C->data[k] = L->data[i];
			i++;
			k++;
		}
		else
		{
			C->data[k] = X->data[j];
			j++;
			k++;
		}
	}
	//程序运行到这里的时候 肯定有一个已经比完了
	if (i == L->length)
	{
		while (j != X->length)
		{
			C->data[k] = X->data[j];
			j++;
			k++;
		}
	}
	if (j == X->length)
	{
		while (i != L->length)
		{
			C->data[k] = L->data[i];
			i++;
			k++;
		}
	}
	C->length = k;
	printf("C数组的长%d L%d X%d \n", k, L->length, X->length);
}

4 从顺序表中删除最小的元素(假设唯一),并由函数返回被删除元素的值。空出的元素由最后一个元素填补。

ElementType Delete_min(seqlist * L)
{
	int flag=0;
	int min =10000;
	for (int i = 0; i < L->length; i++)
	{
		if (L->data[i] < min)
		{
			flag = i;
			min = L->data[i];
		}
	}
	L->data[flag] = L->data[L->length - 1];
	L->length--;
	return min;
}

5 已知长度为n的线性表L采用顺序存储结构,编写空间复杂度为O(1)的算法,该算法删除线性表中所有值在x到y(x<=y)之间的数据元素。

个人感觉题目说的不清楚 你空出来的元素是用最后一个元素补上呢 还是后面依次填上来

void Delete_xy(seqlist* L, ElementType x, ElementType y)
{
	int k = 0;
	for (int i = 0; i < L->length; i++)
	{
		//不需要被删除的数据 依次排开
		if (!(L->data[i] >= x && L->data[i] <= y))
		{
			L->data[k] = L->data[i];
			k++;
		}
	}
	L->length = k;
}

6 [2010年统考]设将n(n>1个整数)存放在一维数组R中。试设计一个时间复杂度和空间复杂度都尽可能高校的算法,将R中保存的序列循环左移p位(0<p<n)个位置,即将R中的数据由(X0,X1...X(n-1))变换为(Xp,Xp+1,....Xn-1,X0,X1,....,Xp-1)要求:1 给出算法的基本设计思想 2 根据算法设计思想采用C语言描述,关键之处给出注释 3 说明你所设计的算法的时间复杂度和空间复杂度。

下面分别贴出我一开始写的代码和标准代码

void LeftMove(seqlist* R, seqlist* L, int p)
{
	//存放左移溢出的数据
	for (int i = 0; i < p; i++)
	{
		L->data[i] = R->data[i];
	}
	for (int i = p; i < R->length; i++)
	{
		R->data[i - p] = R->data[i];
	}
	for (int i = 0; i < p; i++)
	{
		R->data[i + p] = L->data[i];
	}
}

标准答案

//给一个数组 他会把里面的数据原地逆置 你得划定一个范围
void New_Reverse(seqlist* L, int left, int right)
{
	int i = left;
	int j = right;
	while (i < j)
	{
		ElementType temp=L->data[j];
		L->data[j] = L->data[i];
		L->data[i] = temp;
		i++;
		j--;
	}
}
//标准答案左移
void LeftShift(seqlist* L, int p)
{
	if (p > 0 && p < L->length)
	{
		//全部逆置
		New_Reverse(L, 0, L->length - 1);
		//逆置前面n-p个
		New_Reverse(L, 0, L->length - 1 - p);
		//逆置后面的p个
		New_Reverse(L, L->length - p, L->length - 1);
	}
}

测试这些函数用的main函数

int main() {
	/*ElementType x ;*/
	seqlist L,X,C;
	InitList(&L);
	InitList(&X);
	InitList(&C);


	//为什么啊 还是指针不熟悉我感觉

	Insert(&L, 1, 10);
	Insert(&L, 1, 9);
	Insert(&L, 1, 8);
	Insert(&L, 1, 7);
	Insert(&L, 1, 100);
	Insert(&L, 1, 20);
	Insert(&L, 1, 17);
	Insert(&L, 1, 19);
	PrintList(&L);
	printf("找出最小值:\n");
	int min=Delete_min(&L);
	printf("min是%d\n", min);
	PrintList(&L);
	printf("左移4位\n");
	/*LeftMove(&L, &C, 4);*/
	LeftShift(&L, 4);
	PrintList(&L);

	printf("删除10-100 内的数字\n");
	Delete_xy(&L, 10, 100);
	PrintList(&L);

	Insert(&X, 1, 8);
	Insert(&X, 1, 44);
	Insert(&X, 1, 76);
	Insert(&X, 1, 200);
	Insert(&X, 1, 123);
	Insert(&X, 1, 5);
	Insert(&X, 1, 11);
	Insert(&X, 1,888);
	printf("另一个队列\n");
	PrintList(&X);
	Sort(&X,0,X.length-1);
	PrintList(&X);


	printf("排序前\n");

	PrintList(&L);
	//printf("删除的这个数是 %d\n",x);
	/*printf("%d\n",Findlocate(&L, 2));*/
	Moveodd(&L);
	printf("排序后\n");
	PrintList(&L);
	Reverse(&L);
	PrintList(&L);
	printf("快排开始\n");
	Sort(&L, 0, L.length-1);
	printf("快排结束\n");
	PrintList(&L);
	printf("-----------------------------------------\n");
	Merge(&L, &X, &C);
	PrintList(&L);
	PrintList(&X);
	PrintList(&C);


	//Insert(L, 2, 20);
	//PrintList(L);
	//Insert(L, 1, 8);
	//PrintList(L);
	//Insert(L, 1, 9);
	//PrintList(L);
	//Insert(L, 1, 7);
	//PrintList(L);
	//Delete(L, 1, x);
	//PrintList(L);
	//PrintList(L);
	//
	return 0;
}