tips:题目来源王道考研书数据结构篇
1、从顺序表中删除具有最小元素值的元素(假设唯一),并由函数返回被删元素的值。空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。
算法思想:搜索整个顺序表,查找最小值元素并记住其位置,搜索结束后用最后一个元素填补空出的原最小值元素的位置。
参考代码:
//1、从顺序表中删除具有最小元素值的元素(假设唯一),并由函数返回被删元素的值。
// 空出的位置由最后一个元素填补,若顺序表为空,则显示出错信息并退出运行。
#define MaxSize 50
#include<stdio.h>
typedef struct SqList {
int data[MaxSize];
int length;
};
void InitList(SqList &L) {
L.length = 0;
}
bool ListInsert(SqList &L,int i,int e) {
if (i<1 || i>L.length+1)
return false;
if (L.length >= MaxSize)
return false;
for (int j = L.length; j >= i; j--)
L.data[j] = L.data[j - 1];
L.data[i-1] = e;
L.length++;
return true;
}
bool Del_Min(SqList &L,int &e) {
//首先判断表的长度,空表则返回错误并退出
if (L.length == 0)
return false;
e = L.data[0];//假设最小的是L.data[0]
int pos = 0;
for (int i = 1; i < L.length; i++) {
if (L.data[i] < e) {//将e分别和序列中每个数比较,比e小则赋值给e
e = L.data[i];
pos = i;//记录当前e对应L.data[index],index的值
}
}
L.data[pos] = L.data[L.length-1];//将最后一位交换到删除的地方
L.length--;
return true;
}
int main() {
SqList L1;
InitList(L1);
ListInsert(L1, 1, 1);
ListInsert(L1, 2, 2);
ListInsert(L1, 3, 3);
ListInsert(L1, 4, 4);
ListInsert(L1, 5, 5);
for (int i = 0; i < L1.length; i++) {
printf("%d\n", L1.data[i]);
}
//调用Del_Min()
int elem = 0;
Del_Min(L1, elem);
for (int i = 0; i < L1.length; i++) {
printf("L1[%d]=%d\n", i, L1.data[i]);
}
printf("elem=%d\n", elem);
}
2、设计一个高效算法,将顺序表L的所有元素逆置要求算法的空间复杂度为O(1)。
算法思想:扫描顺序表L的前半部分元素,对于元素L.data[i](0<=i<L.length/2),将其与后半段的对应元素L.data[L.length-i-1]进行交换
//设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)。
#define MaxSize 50
#include<stdio.h>
typedef struct SqList {
int data[MaxSize];
int length;
};
void InitList(SqList &L) {
L.length = 0;
}
bool ListInsert(SqList &L,int i,int e) {
if (i<1 || i>L.length+1)
return false;
if (L.length >= MaxSize)
return false;
for (int j = L.length; j >= i; j--)
L.data[j] = L.data[j - 1];
L.data[i-1] = e;
L.length++;
return true;
}
void ListReverse(SqList& L) {
int temp = 0;
for (int i = 0; i < L.length / 2; i++) {
temp = L.data[L.length - i - 1];
L.data[L.length - i - 1] = L.data[i];
L.data[i] = temp;
}
}
int main() {
SqList L1;
InitList(L1);
ListInsert(L1, 1, 1);
ListInsert(L1, 2, 2);
ListInsert(L1, 3, 3);
ListInsert(L1, 4, 4);
ListInsert(L1, 5, 5);
printf("原顺序表:\n");
for (int i = 0; i < L1.length; i++) {
printf("%d\n", L1.data[i]);
}
printf("翻转后:\n");
ListReverse(L1);
for (int i = 0; i < L1.length; i++) {
printf("%d\n", L1.data[i]);
}
}
3、对长度为n的顺序表L,编写一个时间复杂的为O(n),空间复杂度为O(1)的算法,该算法删除顺序表中所有值为x的数据元素
代码:
//对长度为n的顺序表L,编写一个时间复杂的为O(n),空间复杂度为O(1)的算法,
// 该算法删除顺序表中所有值为x的数据元素
#define MaxSize 50
#include<stdio.h>
typedef struct SqList {
int data[MaxSize];
int length;
};
void InitList(SqList &L) {
L.length = 0;
}
bool ListInsert(SqList &L,int i,int e) {
if (i<1 || i>L.length+1)
return false;
if (L.length >= MaxSize)
return false;
for (int j = L.length; j >= i; j--)
L.data[j] = L.data[j - 1];
L.data[i-1] = e;
L.length++;
return true;
}
void Delx_1(SqList& L, int x) {
int k = 0;
for (int i = 0; i < L.length; i++) {
if (L.data[i] != x) {
L.data[k] = L.data[i];
k++;
}
}
L.length = k;
}
int main() {
SqList L1;
InitList(L1);
ListInsert(L1, 1, 1);
ListInsert(L1, 2, 2);
ListInsert(L1, 3, 3);
ListInsert(L1, 4, 2);
ListInsert(L1, 5, 5);
printf("原顺序表:\n");
for (int i = 0; i < L1.length; i++) {
printf("%d\n", L1.data[i]);
}
printf("删除顺序表中值为2的\n");
Delx_1(L1,2);
for (int i = 0; i < L1.length; i++) {
printf("%d\n", L1.data[i]);
}
}
4、从顺序表中删除其值在定值s和t之间(包含s和t,要求s<t)的所有元素,若s或t不合理或顺序表为空,则显示出错信息并退出运行。
参考代码:
//从顺序表中删除其值在定值s和t之间(包含s和t,要求s<t)的所有元素,
// 若s或t不合理或顺序表为空,则显示出错信息并退出运行。
#define MaxSize 50
#include<stdio.h>
typedef struct SqList {
int data[MaxSize];
int length;
};
void InitList(SqList &L) {
L.length = 0;
}
bool ListInsert(SqList &L,int i,int e) {
if (i<1 || i>L.length+1)
return false;
if (L.length >= MaxSize)
return false;
for (int j = L.length; j >= i; j--)
L.data[j] = L.data[j - 1];
L.data[i-1] = e;
L.length++;
return true;
}
bool Delx_2(SqList& L, int s,int t ) {
if (L.length == 0 || s > t)
return false;
int k = 0;
for (int i = 0; i < L.length; i++) {
if (L.data[i] >= s && L.data[i] <= t)
k++;
else
L.data[i - k] = L.data[i];
}
L.length = L.length - k;
return true;
}
int main() {
SqList L1;
InitList(L1);
ListInsert(L1, 1, 1);
ListInsert(L1, 2, 2);
ListInsert(L1, 3, 3);
ListInsert(L1, 4, 2);
ListInsert(L1, 5, 5);
printf("原顺序表:\n");
for (int i = 0; i < L1.length; i++) {
printf("%d\n", L1.data[i]);
}
printf("删除顺序表中值在[2,3]范围内的值\n");
Delx_2(L1,2,3);
for (int i = 0; i < L1.length; i++) {
printf("%d\n", L1.data[i]);
}
}
5、从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不相同。
//5、从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不相同。
#define MaxSize 50
#include<stdio.h>
typedef struct SqList {
int data[MaxSize];
int length;
};
void InitList(SqList &L) {
L.length = 0;
}
bool ListInsert(SqList &L,int i,int e) {
if (i<1 || i>L.length+1)
return false;
if (L.length >= MaxSize)
return false;
for (int j = L.length; j >= i; j--)
L.data[j] = L.data[j - 1];
L.data[i-1] = e;
L.length++;
return true;
}
//5、从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不相同。
bool Del_x3(SqList& L) {
if (L.length == 0)
return false;
int i = 0;
for (int j = 1; j < L.length; j++) {
if (L.data[i] != L.data[j]) {
i++;
L.data[i] = L.data[j];
}
}
L.length = i + 1;
}
int main() {
SqList L1;
InitList(L1);
ListInsert(L1, 1, 1);
ListInsert(L1, 2, 2);
ListInsert(L1, 3, 2);
ListInsert(L1, 4, 2);
ListInsert(L1, 5, 5);
printf("原顺序表:\n");
for (int i = 0; i < L1.length; i++) {
printf("%d\n", L1.data[i]);
}
printf("删除有序表中重复的值:\n");
Del_x3(L1);
for (int i = 0; i < L1.length; i++) {
printf("%d\n", L1.data[i]);
}
}
6、将两个有序顺序表合并成一个新的有序顺序表,并由函数返回结果顺序表
#define MaxSize 50
#include<stdio.h>
typedef struct SqList {
int data[MaxSize];
int length;
};
void InitList(SqList &L) {
L.length = 0;
}
bool ListInsert(SqList &L,int i,int e) {
if (i<1 || i>L.length+1)
return false;
if (L.length >= MaxSize)
return false;
for (int j = L.length; j >= i; j--)
L.data[j] = L.data[j - 1];
L.data[i-1] = e;
L.length++;
return true;
}
//6、将两个有序顺序表合并成一个新的有序顺序表,并由函数返回结果顺序表
bool Merge(SqList A, SqList B, SqList &C) {
//将有序顺序表A和B合并成一个新的表C
if (A.length + B.length > MaxSize)
return false;
int i = 0;
int j = 0;
int k = 0;
while (i < A.length && j < B.length) {
if (A.data[i] <= B.data[j]) {
C.data[k] = A.data[i];
k++;
i++;
}
else
{
C.data[k] = B.data[j];
k++;
j++;
}
}
//假设A还没比较完
while (i < A.length){
C.data[k++] = A.data[i++];
}
//同理假设B还没比较完
while (j < B.length) {
C.data[k++] = B.data[j++];
}
C.length = k;
return true;
}
int main() {
SqList L1, L2, L3;
//初始化表
InitList(L1);
InitList(L2);
InitList(L3);
ListInsert(L1, 1, 1);
ListInsert(L1, 2, 2);
ListInsert(L1, 3, 3);
ListInsert(L2, 1, 4);
ListInsert(L2, 2, 5);
ListInsert(L2, 3, 6);
printf("有序顺序表L1\n");
for (int i = 0; i < L1.length; i++) {
printf("L1.data[%d]=%d\n", i, L1.data[i]);
}
printf("有序顺序表L2\n");
for (int i = 0; i < L2.length; i++) {
printf("L2.data[%d]=%d\n", i, L2.data[i]);
}
printf("L1和L2合并为有序顺序表L3\n");
Merge(L1, L2, L3);
for (int i = 0; i < L3.length; i++) {
printf("L3.data[%d]=%d\n", i, L3.data[i]);
}
}
7、已知有一组数组A[m+n]中依次存放两个线性表(a1,a2,a3,...,am)和(b1,b2,b3,...,bn),编写一个函数,将数组中两个顺序表的位置交换,即将(b1,b2,b3,...,bn)放在(a1,a2,a3,...,am)的前面。
算法思想:首先将数组A[m+n]中的全部元素(a1,a2,a3,...,am,b1,b2,b3,...,bn)原地逆置为(bn,bn-1,bn-2...b1,an,an-1,an-2...a1),然后分别对前n个元素和后m个元素逆置,即可得到(b1,b2,b3,...,bn,a1,a2,a3,...,am),从而实现位置交换。
参考代码:
#include<stdio.h>
typedef int DataType;
void Reverse(DataType A[], int left, int right,int arraySize) {
if (left == right || right >= arraySize) {
return;
}
int mid = (left + right) / 2;
int temp = 0;
for (int i = 0; i <= mid - left; i++) {
temp = A[right - i];
A[right - i] = A[left + i];
A[left + i] = temp;
}
}
void Exchange(DataType A[], int m, int n, int arraySize) {
Reverse(A, 0, m + n - 1, arraySize);
Reverse(A, 0, n - 1, arraySize);
Reverse(A, n, m + n - 1, arraySize);
}
int main() {
int A[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("原数组是\n");
for (int i = 0; i < 10; i++) {
printf("%d\n", A[i]);
}
printf("逆置后的数组是\n");
Exchange(A,5,5,10);
for (int i = 0; i < 10; i++) {
printf("%d\n", A[i]);
}
}
时间复杂度分析:O(n)
8、线性表(a1,a2,a3...,an)中的元素递增有序且按顺序存储于计算机内。要求设计一个算法,完成最少时间在表中查找数值为x的元素,若找到,则将其与后继元素位置相交换,若找不到,则将其插入到表中使表中元素仍递增有序。
算法思想:顺序存储的线性表递增有序,可以顺序查找也可以折半查找。题目要求最短时间,所以本题用折半查找法。
参考代码:
#define MaxSize 50
#include<stdio.h>
typedef struct SqList {
int data[MaxSize];
int length;
};
void InitList(SqList &L) {
L.length = 0;
}
bool ListInsert(SqList &L,int i,int e) {
if (i<1 || i>L.length+1)
return false;
if (L.length >= MaxSize)
return false;
for (int j = L.length; j >= i; j--)
L.data[j] = L.data[j - 1];
L.data[i-1] = e;
L.length++;
return true;
}
//线性表(a1,a2,a3...,an)中的元素递增有序且按顺序存储于计算机内。
// 要求设计一个算法,完成最少时间在表中查找数值为x的元素,
// 若找到,则将其与后继元素位置相交换,
// 若找不到,则将其插入到表中使表中元素仍递增有序。
void SearchExchangeInsert(SqList& L, int x) {
int left = 0, right = L.length - 1,mid;
//折半查找法
while (left <= right) {
mid = (left + right) / 2;
if (L.data[mid] == x)
break;//若为mid,直接退出循环
else if (L.data[mid] < x) {
right = mid - 1;//若小于则去左半部分查找
}
else{
left = mid + 1;//若大于则去右半部分查找
}
}
if (L.data[mid] == x && mid != L.length - 1) {//若找到,则将其与后继元素位置相交换
int temp = L.data[mid];
L.data[mid] = L.data[mid + 1];
L.data[mid + 1] = temp;
}
if (left > right) {//若找不到,则将其插入到表中使表中元素仍递增有序
int i;
for (i = L.length - 1; i > right; i--) {
L.data[i + 1] = L.data[i];
}
L.data[i + 1] = x;
L.length++;
}
}
int main() {
SqList L1;
//初始化表
InitList(L1);
ListInsert(L1, 1, 1);
ListInsert(L1, 2, 2);
ListInsert(L1, 3, 4);
ListInsert(L1, 4, 4);
ListInsert(L1, 5, 5);
printf("有序顺序表L1\n");
for (int i = 0; i < L1.length; i++) {
printf("L1.data[%d]=%d\n", i, L1.data[i]);
}
printf("查找元素x:\n");
SearchExchangeInsert(L1, 3);
for (int i = 0; i < L1.length; i++) {
printf("L1.data[%d]=%d\n", i, L1.data[i]);
}
}
9、给定三个序列A,B,C,长度均为n,且无重复元素的递增数列,请设计一个时间上尽可能高效的算法,逐行输出同时同时存在与这三个序列中的所有元素。例如,数组A为[1,2,3]数组B[2,3,4]数组C[-1,0,2],则输出2
算法思想:三个指针分别从数组起始位置开始遍历数组,找到当前三个指针中指向最大的数,其余两个指针分别右移
#define MaxSize 100
#include<stdio.h>
typedef struct SqList {
int data[MaxSize];
int length;
};
int GetMax(int a, int b);
void InitList(SqList& L);
void InitList(SqList& L) {
L.length = 0;
}
bool ListInsert(SqList& L, int i, int e) {
if (i<1 || i>L.length + 1)
return false;
if (L.length >= MaxSize)
return false;
for (int j = L.length-1; j >i; j--) {
L.data[j] = L.data[j + 1];
}
L.data[i-1] = e;
L.length++;
return true;
}
//给定三个序列A,B,C,长度均为n,且无重复元素的递增数列,请设计一个时间上尽可能高效的算法,
//逐行输出同时同时存在与这三个序列中的所有元素。例如,数组A为[1,2,3]数组B[2,3,4]数组C[-1,0,2],则输出2。
void SearchSame(SqList L1, SqList L2, SqList L3, int n) {
int i = 0, j = 0, k = 0;
while(i<n&&j<n&&k<n){
if (L1.data[i] == L2.data[j] && L2.data[j] == L3.data[k]) {
printf("%d", L1.data[i]);
i++;
j++;
k++;
}
else
{
int maxnum = GetMax(L1.data[i], (L2.data[j], L3.data[k]));
if (L1.data[i] < maxnum)
i++;
if (L2.data[j] < maxnum)
j++;
if (L3.data[k] < maxnum)
k++;
}
}
}
int GetMax(int a,int b) {
if (a > b)
return a;
else
{
return b;
}
}
int main() {
SqList L1, L2, L3;
InitList(L1);
InitList(L2);
InitList(L3);
ListInsert(L1, 1, 1);
ListInsert(L1, 2, 2);
ListInsert(L1, 3, 3);
ListInsert(L2, 1, 2);
ListInsert(L2, 2, 3);
ListInsert(L2, 3, 4);
ListInsert(L3, 1, -1);
ListInsert(L3, 2, 0);
ListInsert(L3, 3, 2);
SearchSame(L1, L2, L3, 3);
}