#include "stdio.h"
#include "windows.h"
#include "stdbool.h"
#define SqListMaxSize 50
#define ElemType int
#define SeqListMaxSize 50
#define OVERFLOW 0
/*
线性表(顺序存储结构)
*/
typedef struct {
ElemType data[SqListMaxSize];
int length;
}SqList;
/*
线性表(随机存储结构)
*/
typedef struct {
ElemType *data;
int MaxSize, length;
}SeqList;
/*
线性表(顺序存储结构)插入
*/
bool SqListInsert(SqList *L, int i, ElemType e) {
if (i < 1 || i > L->length + 1)
return false;
if (L->length >= SqListMaxSize)
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 SeqListInsert(SeqList *L, int i, ElemType e) {
if (i < 1 || i > L->length + 1)
return false;
if (L->length >= SqListMaxSize)
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 SeqListInsertByOrder(SeqList *L, ElemType e) {
int i;
if (L->length >= SqListMaxSize)
return false;
for (i = 0; i < L->length; i++) {
if (L->data[i] >= e) {
for (int j = L->length; j > i; j--)
L->data[j] = L->data[j - 1];
L->data[i] = e;
L->length++;
return true;
}
}
L->data[L->length] = e;
L->length++;
return true;
}
/*
线性表(随机存储结构)顺序插入(插到最后一位)
*/
bool SeqListInsertEnd(SeqList *L, ElemType e) {
if (L->length >= SqListMaxSize)
return false;
L->data[L->length] = e;
L->length++;
return true;
}
/*
线性表(顺序存储结构)删除
*/
bool SqListDelete(SqList *L, int i,ElemType *e) {
if (i < 1 || i > L->length + 1)
return false;
e = L->data[i - 1];
for (int j = i; j < L->length; j++)
L->data[j - 1] = L->data[j];
L->length--;
return true;
}
/*
线性表(随机存储结构)删除
*/
bool SeqListDelete(SeqList *L, int i, ElemType *e) {
if (i < 1 || i > L->length + 1)
return false;
e = L->data[i - 1];
for (int j = i; j < L->length; j++)
L->data[j - 1] = L->data[j];
L->length--;
return true;
}
/*
线性表(顺序存储结构)顺序查找
*/
int SqLocateElem(SqList *L, ElemType e) {
int i;
for (i = 0; i < L->length; i++)
if (L->data[i] == e)
return i + 1;
return 0;
}
/*
线性表(随机存储结构)随机查找
*/
int SeqLocateElem(SeqList *L, ElemType e) {
int i;
for (i = 0; i < L->length; i++)
if (L->data[i] == e)
return i + 1;
return 0;
}
void PrintSeqList(SeqList *L) {
int i;
printf("线性表数据为:");
for(i = 0; i < L->length; i++) {
printf("[%d]%d ", i + 1, L->data[i]);
}
printf("\n");
}
/*
线性表(随机存储结构)初始化
*/
bool InitSeqList(SeqList* L) {
L->data = (ElemType*)malloc(sizeof(ElemType)*SeqListMaxSize);
if (!L->data) exit(OVERFLOW);
L->length = 0;
return true;
}
void PrintArray(ElemType A[],int length) {
printf("数组数据为:");
for (int i = 0; i < length; i++) {
printf("[%d]%d ", i + 1, A[i]);
}
printf("\n");
}
/*
找出最小值,并用最后的元素填充 时间复杂度O(n),空间复杂度O(1)
*/
ElemType Mos_2_2_2_1(SeqList* L) {
int i;
int min = L->data[0],loc = 0;
if (!L->data) {
printf("顺序表为空!\n");
exit(OVERFLOW);
}
for (i = 0; i < L->length; i++) {
if (L->data[i] < min) {
min = L->data[i];
loc = i;
}
}
L->data[loc] = L->data[L->length - 1];
L->length--;
//SeqListDelete(&L, loc);
return min;
}
/*
逆置算法 时间复杂度O(n),空间复杂度O(1)
*/
void Mos_2_2_2_2(SeqList* L) {
ElemType e;
int i = 0;
for (i = 0; i < L->length / 2; i++) {
e = L->data[i];
L->data[i] = L->data[L->length - i - 1];
L->data[L->length - i - 1] = e;
}
}
/*
删除所有值为x元素的算法 时间复杂度O(n),空间复杂度O(1)
*/
void Mos_2_2_2_3(SeqList* L,ElemType x) {
int i,k = 0;
for (i = 0; i < L->length; i++) {
if (L->data[i] == x) {
k++;
}
else {
L->data[i - k] = L->data[i];
}
}
L->length -= k;
}
/*
删除所有s到t之间的值的算法 时间复杂度O(n),空间复杂度O(1)
*/
void Mos_2_2_2_4(SeqList* L, ElemType s, ElemType t) {
int i,k=0;
if (s >= t || !L->data) {
printf("给定值报错!\n");
exit(OVERFLOW);
}
for (i = 0; i < L->length; i++) {
if (L->data[i] < t && L->data[i] > s) {
k++;
}
else {
L->data[i - k] = L->data[i];
}
}
L->length -= k;
}
/*
删除所有s到t(包括边界)之间的值的算法 时间复杂度O(n),空间复杂度O(1)
*/
void Mos_2_2_2_5(SeqList* L, ElemType s, ElemType t) {
int i, k = 0;
if (s >= t || !L->data) {
printf("给定值报错!\n");
exit(OVERFLOW);
}
for (i = 0; i < L->length; i++) {
if (L->data[i] <= t && L->data[i] >= s) {
k++;
}
else {
L->data[i - k] = L->data[i];
}
}
L->length -= k;
}
/*
删除所有相同的元素 时间复杂度O(n),空间复杂度O(n)
*/
void Mos_2_2_2_6(SeqList* L) {
int i, k = 0;
int rep[SeqListMaxSize] = { 0 };
for (i = 0; i < L->length; i++) {
rep[L->data[i]]++;
if (rep[L->data[i]] > 1) {
k++;
}
else {
L->data[i - k] = L->data[i];
}
}
L->length -= k;
}
/*
合并两个顺序表到CL 时间复杂度O(n) 空间复杂度O(1)
*/
void Mos_2_2_2_7(SeqList* AL, SeqList* BL, SeqList* CL) {
int i = 0, j = 0,length = AL->length + BL->length;
CL->length = length;
while (i + j < length) {
if (i >= AL->length) {
CL->data[i + j] = BL->data[j++];
continue;
}
if (j >= BL->length) {
CL->data[i + j] = AL->data[i++];
continue;
}
if ( AL->data[i] < BL->data[j]) {
CL->data[i + j] = AL->data[i++];
}else{
CL->data[i + j] = BL->data[j++];
}
}
}
/*
将两个线性表按注入A数组,先AL,后BL
*/
void Mos_2_2_2_8_1(ElemType A[], SeqList* AL, SeqList* BL) {
int i,j;
for (i = 0; i < AL->length; i++) {
A[i] = AL->data[i];
}
for (j = 0; j < BL->length; j++) {
A[i+j] = BL->data[j];
}
}
/*
将A数组中存放的两个线性表调转位置 时间复杂度O(n) 空间复杂度O(1)
*/
void Mos_2_2_2_8(ElemType A[],int left, int right, int arraySize) {
int i,temp;
for (i = 0; i < arraySize / 2; i++) {
temp = A[i];
A[i] = A[arraySize - i - 1];
A[arraySize - i - 1] = temp;
}
for (i = 0; i < right / 2; i++) {
temp = A[i];
A[i] = A[right - i - 1];
A[right - i - 1] = temp;
}
for (i = 0; i < left / 2; i++) {
temp = A[right+i];
A[right + i] = A[arraySize - i - 1];
A[arraySize - i - 1] = temp;
}
}
/*
使用折半查找法,找到线性表中对应的元素,并和后继元素交换位置,若找不到,则在相应位置按顺序插入该元素
时间复杂度O(log2n) 空间复杂度O(1)
*/
void Mos_2_2_2_9(SeqList* L, ElemType e) {
int i,low = 0,high = L->length - 1,mid,temp;
while (low < high) {
mid = (low + high) / 2;
if (L->data[mid] == e) {
temp = L->data[mid];
L->data[mid] = L->data[mid + 1];
L->data[mid + 1] = temp;
return;
}
if (L->data[mid] > e) {
high = mid - 1;
}
if (L->data[mid] < e) {
low = mid + 1;
}
}
for ( i = L->length - 1; i > high; i--) {
L->data[i+1] = L->data[i];
}
L->data[i+1] = e;
L->length++;
}
/*
将A数组中的元素循环左移P位
算法思想:
将前p个元素看作数组B,后n-p个元素看作数组C,分别转置B与C,然后将B与C一起转置,就实现了对A数组的循环左移P位
时间复杂度:O(n),空间复杂度O(1)
*/
void Mos_2_2_2_10(ElemType A[], int p, int arraySize) {
int i, temp,left = p,right = arraySize - p;
for (i = 0; i < arraySize / 2; i++) {
temp = A[i];
A[i] = A[arraySize - i - 1];
A[arraySize - i - 1] = temp;
}
for (i = 0; i < right / 2; i++) {
temp = A[i];
A[i] = A[right - i - 1];
A[right - i - 1] = temp;
}
for (i = 0; i < left / 2; i++) {
temp = A[right + i];
A[right + i] = A[arraySize - i - 1];
A[arraySize - i - 1] = temp;
}
}
/*
找到AL与BL两个序列的一个中位数,[L/2](从1开始)
设计思想:
1、找到AL与BL的中位数
2、三种情况:
(1)如果AL的中位数小于BL中位数,则舍弃AL小的一半和BL大的一半
(2)如果AL的中位数大于BL中位数,则舍弃AL大的一半和BL小的一半
(3)如果AL的中位数等于BL中位数,则直接返回该值
3、在剩下的两个序列中,重复2过程,直到AL和BL都仅有一个元素,进入4
4、返回AL和BL中较小的那一个元素作为中位数
时间复杂度:O(log2n) 空间复杂度O(1)
*/
int Mos_2_2_2_11(SeqList *AL, SeqList *BL) {
int lowA = 0, lowB = 0, highA = AL->length - 1, highB = BL->length - 1, midA, midB;
while (lowA != highA || lowB != highB) {
midA = (lowA + highA) / 2;
midB = (lowB + highB) / 2 ;
if (AL->data[midA] == BL->data[midB]) {
return AL->data[midA];
}
if (AL->data[midA] < BL->data[midB]) {
if ((lowA + highA) % 2 == 0) {
lowA = midA;
highB = midB;
}
else {
lowA = midA+1;
highB = midB;
}
}
else {
if ((lowA + highA) % 2 == 0) {
lowB = midB;
highA = midA;
}
else {
lowB = midB+1;
highA = midA;
}
}
}
return AL->data[lowA] < BL->data[lowB] ? AL->data[lowA] : BL->data[lowB];
}
/*
该算法用于找出主要数,主要数的定义是,在数组中出现次数在 数组长度/2 以上的数字
算法思想:
1、以第一个元素为候选的主要数,然后依次向后扫描所有的数,将初始的计数值Count=1、CountMax=1
2、如果当前元素等于候选的主要数,则Count++,CountMax++,然后进行下一次计数
3、如果当前元素不等于候选的主要数,则判断Count是否大于0
(1)如果不大于0,则代表候选的主要数不是真正的主要数,将当前元素设置为候选的主要数,并重置Count与CountMax
(2)如果大于0,则使Count--
4、在循环结束后,判断CountMax是否大于n/2,若是,则代表为主要数,若不是,则代表没有主要数反回-1
时间复杂度O(n),空间复杂度O(1)
*/
int Mos_2_2_2_12(int A[],int length) {
int count=1, countMax=1,c = A[0],i;
for (i = 1; i < length; i++) {
if (A[i] == c) {
count++;
countMax++;
}
else {
if (count>0){
count--;
}
else {
c = A[i];
count = 1;
countMax = 1;
}
}
}
if (countMax > length / 2)return c;
return -1;
}
//void Mos_2_2_2_8(ElemType A[],int right,int arraySize) {该方法有问题
// int i = 0, j = right;
// ElemType temp1,temp2;
// if (right <= 0 || right >= arraySize)
// return true;
// for (int i = 0; i < right && right + i < arraySize; i++) {
// temp1 = A[i];
// temp2 = A[right+i-(arraySize-right)];
// A[i] = A[right+i];
// A[right + i - (arraySize - right)] = temp1;
// A[right + i] = temp2;
// }
//}
/*
该算法用于找出数组A中未出现的最小正整数
算法思路:
利用空间换时间,制作一个长度为n的数组B,用于表示A数组中每个对应元素出现的次数
扫描A数组,如果A[i]-1>n,那么使B数组的长度bLength--,舍弃当前元素,反之,令B[A[i]]++;
然后扫描B数组,只要出现B[i]=0则,返回i+1作为结果,
如果B数组中没有值为0,则返回bLength+1为结果
时间复杂度O(n),空间复杂度O(n)
*/
int Mos_2_2_2_13(int A[], int length) {
int B[SeqListMaxSize] = { 0 },bLength = length;
for (int i = 0; i < length; i++) {
if (A[i] - 1 <= length)
B[A[i] - 1]++;
else
bLength--;
}
for (int i = 0; i < bLength; i++) {
if (B[i] == 0) {
return i+1;
}
}
return bLength +1;
}
int main() {
SeqList L,BL,CL,DL,EL,FL;
ElemType A[SeqListMaxSize];
InitSeqList(&L);
InitSeqList(&BL);
InitSeqList(&CL);
InitSeqList(&DL);
InitSeqList(&EL);
InitSeqList(&FL);
for (int i = 0; i < 5; i++) {
SeqListInsertByOrder(&DL, i);
SeqListInsertByOrder(&DL, i);
}
for (int i = 6; i < 10; i++) {
SeqListInsertByOrder(&DL, i);
SeqListInsertByOrder(&DL, i);
}
for (int i = 0; i < 3; i++)
SeqListInsertEnd(&BL, i);
for(int i = 0;i < 10;i++)
SeqListInsertByOrder(&L, i);
for (int i = 0; i < 3; i++)
SeqListInsertEnd(&L, 3);
for (int i = 0; i < 4; i++)
SeqListInsertByOrder(&L, 2);
for (int i = 0; i < 2; i++)
SeqListInsertEnd(&L, 8);
PrintSeqList(&L);
Mos_2_2_2_1(&L);
PrintSeqList(&L);
Mos_2_2_2_2(&L);
PrintSeqList(&L);
Mos_2_2_2_3(&L,3);
PrintSeqList(&L);
Mos_2_2_2_4(&L, 5, 7);
PrintSeqList(&L);
Mos_2_2_2_5(&L, 5, 7);
PrintSeqList(&L);
Mos_2_2_2_6(&L);
PrintSeqList(&L);
Mos_2_2_2_7(&L, &BL, &CL);
PrintSeqList(&CL);
Mos_2_2_2_8_1(A, &L, &BL);
PrintArray(A, L.length + BL.length);
Mos_2_2_2_8(A, L.length,BL.length, L.length + BL.length);
PrintArray(A,L.length + BL.length);
PrintSeqList(&DL);
Mos_2_2_2_9(&DL, 5);
PrintSeqList(&DL);
PrintArray(A, L.length + BL.length);
Mos_2_2_2_10(A, 3, L.length + BL.length);
PrintArray(A, L.length + BL.length);
for (int i = 1; i < 4; i++)
SeqListInsertByOrder(&EL, i);
for (int i = 2; i < 5; i++)
SeqListInsertByOrder(&FL, i);
PrintSeqList(&EL);
PrintSeqList(&FL);
printf("中位数为%d\n",Mos_2_2_2_11(&EL, &FL));
for (int i = 2; i < 5; i++)
SeqListInsertByOrder(&FL, 3);
Mos_2_2_2_8_1(A, &EL, &FL);
PrintArray(A, EL.length + FL.length);
printf("主要数为:%d \n", Mos_2_2_2_12(A, EL.length + FL.length));
printf("未出现的最小正整数为:%d\n", Mos_2_2_2_13(A, EL.length + FL.length));
system("pause");
return 0;
}
注1:单链表和顺序表删除所有值为X的元素的时间复杂度应该都为O(n)参照2.2.3题,但在考研真题当中似乎是没有考虑这一点。