目录
线性表
顺序表
1. 静态顺序表:使用定长数组存储元素。
2. 动态顺序表:使用动态开辟的数组存储。
接口实现
SeqList.h
SeqList.c
Test.c
数组相关面试题
顺序表的问题及思考
#pragma once
#define N 100
typedef int SLDataType;
struct SeqList
{SLDataType a[N];int size;
};
#pragma once
typedef int SLDataType;
struct SeqList
{SLDataType* a;int size;int capacity;//容量
};
#pragma once
typedef int SLDataType;
typedef struct SeqList
{SLDataType* a;int size;int capacity;//容量
}SL;
void SLInit(SL* ps);void SLDestory(SL* ps);void SLCheckCapacity(SL* ps);void SLPushBack(SL* ps, SLDataType x);
void SLpopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLpopFront(SL* ps);void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps, int pos);int SLFind(SL* ps, SLDataType x);
void SLModify(SL* ps, int pos,int x);void SLPrint(SL* ps);
#define _CRT_SECURE_NO_WARNINGS 1
#include"SeqList.h"
#include
#include
#includevoid SLInit(SL* ps) {assert(ps != NULL);ps->a = NULL;ps->size = ps->capacity = 0;
}void SLCheckCapacity(SL* ps)
{assert(ps != NULL);if (ps->capacity == ps->size){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;SLDataType* tmp = realloc(ps->a, newcapacity * sizeof(SLDataType));if (tmp == NULL) {printf("realloc fall\n");exit(-1);}ps->a = tmp;ps->capacity = newcapacity;}
}void SLPushBack(SL* ps, SLDataType x) {assert(ps != NULL);/*SLCheckCapacity(ps);ps->a[ps->size] = x;ps->size++;*/SLInsert(ps, ps->size, x);
}void SLPrint(SL* ps) {assert(ps != NULL);for (int i = 0; i < ps->size; ++i){printf("%d", ps->a[i]);}printf("\n");}void SLDestory(SL* ps)
{assert(ps != NULL);if (ps -> a){free(ps->a);ps->a = NULL;ps->capacity = 0;ps->size = 0;}
}void SLPushFront(SL* ps, SLDataType x) {/*assert(ps != NULL);SLCheckCapacity(ps);int end = ps->size - 1;while (end >= 0){ps->a[end + 1] = ps->a[end];--end;}ps->a[0] = x;ps->size++;*/SLInsert(ps, 0, x);
}void SLpopBack(SL* ps) {assert(ps != NULL);/*if (ps->size == 0){printf("SeqList is empty");return;}*/assert(ps->size > 0);ps->size--;
}void SLpopFront(SL* ps) {assert(ps != NULL);assert(ps->size > 0);/*int begin = 1;while (begin < ps->size){ps->a[begin - 1] = ps->a[begin];++begin;}ps->size--;*/SLErase(ps, 0);
}void SLInsert(SL* ps, int pos, SLDataType x)
{assert(ps != NULL);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = x;ps->size++;}void SLErase(SL* ps, int pos) {assert(ps != NULL);assert(pos >= 0 && pos < ps->size);int begin = pos;while (begin < ps-> size - 1){ps->a[begin] = ps->a[begin + 1];++begin;}ps->size--;
}int SLFind(SL* ps, SLDataType x)
{assert(ps);for (int i = 0; i < ps->size; ++i){if (ps->a[i] == x){return i;}}return -1;
}void SLModify(SL* ps, int pos,int x)
{assert(ps);assert(pos >= 0 && pos < ps->size);ps->a[pos] = x;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
#include
#include
void menu()
{printf("*****************************************************************\n");printf("1、查找 2、修改\n");printf("3、尾插 4、头插\n");printf("5、任意删 6、任意插\n");printf("7、尾删 8、头删\n");printf("9、打印 -1、退出\n");printf("*****************************************************************\n");}int main()
{SL s1;SLInit(&s1);int option ;do {menu();if (scanf("%d", &option) == EOF){printf("scanf输入错误\n");break;}int val, pos;switch (option){case -1:printf("退出\n");exit(0);break;case 1:printf("请输入你要查找的值\n");int x;scanf("%d", &x);int pos = SLFind(&s1, x);printf("在%d位置处\n",pos);break;case 2: {int y;int z;printf("请输入你要修改的值和修改后的值\n");scanf("%d%d", &y, &z);pos = SLFind(&s1, y);if (pos != -1){SLModify(&s1, pos, z);}else{printf("没找到:%d\n", y);}break;}case 3:printf("请连续输入你要尾插的数据,以0结束:\n");scanf("%d", &val);while (val!=0){SLPushBack(&s1, val);scanf("%d", &val);}break;case 4:printf("请连续输入你要头插的数据,以0结束:\n");scanf("%d", &val);while (val != 0){SLPushFront(&s1, val);scanf("%d", &val);}break;case 5:{int y;printf("请输入你要删除的位置\n");scanf("%d", &y);SLErase(&s1, y);break;}case 6:{int y;int x;printf("请输入你要插入的位置,和插入的值\n");scanf("%d%d", &y, &x);SLInsert(&s1, y, x);break;}case 7:SLpopBack(&s1);break;case 8:SLpopFront(&s1);break;case 9:SLPrint(&s1);break;default:exit(-1);break;}} while (option != -1);SLDestory(&s1);return 0;
}
1、分析以下函数的空间复杂度( )
A.O(n)
B.O(n^2)
C.O( 1 )
D.O(nlogn)
int** fun(int n) {int ** s = (int **)malloc(n * sizeof(int *));while(n--)s[n] = (int *)malloc(n * sizeof(int));return s;}
答案解析:
此处开辟的是一个二维数组,数组有n行,每行分别有1,2,3,...n列,所以是n(n + 1)/2个元素空间,空间复杂度为n^2
2、如果一个函数的内部中只定义了一个二维数组a[3][6],请问这个函数的空间复杂度为( )
A.O(n)
B.O(n^2)
C.O( 1 )
D.O(m*n)
答案解析:
函数内部数组的大小是固定的,不论函数运行多少次,所需空间都是固定大小的,因此空间复杂度为O(1)
27. 移除元素 - 力扣(LeetCode)
int removeElement(int* nums, int numsSize, int val){int src = 0, dst = 0;while(src < numsSize){if(nums[src] == val){src++;}else{nums[dst++] = nums[src++];}}return dst;}
int removeElement(int* nums, int numsSize, int val){int j = 0;int i = 0;for(i = 0;i < numsSize; ++i){if(nums[i] == val){for(j = i+1;j < numsSize;j++){ nums[j-1] = nums[j];}numsSize--;i--;}}return numsSize;
}
26. 删除有序数组中的重复项 - 力扣(LeetCode)
int removeDuplicates(int* nums, int numsSize){int left = 0;int right = 0;while(right
88. 合并两个有序数组 - 力扣(LeetCode)
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){int num1right = m - 1;int num2right = n - 1;int a = m + n - 1;while(num1right >= 0 || num2right >= 0){if(num2right < 0){nums1[a--] = nums1[num1right--];}else if(num1right < 0){nums1[a--] = nums2[num2right--];}else if(nums1[num1right] >= nums2[num2right]){nums1[a--] = nums1[num1right--];}else{nums1[a--] = nums2[num2right--];}}
}
1. 中间/头部的插入删除,时间复杂度为O(N) 2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。 3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。 思考:如何解决以上问题呢?去下篇博客看看链表。