考研数据结构算法学习笔记整理 Day1-Day8 线性表
- 前言
- 目录
- Day1 在头结点的单链表L中,删除所有值为x的结点,并释放其空间。假设值为x的结点不唯一,试编写算法以实现上述操作。
- Day2 将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
- Day3 设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)。
- Day4 对长度为n的顺序表L,编写一个时间复杂度为O(n),空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素。(类比Day1)
- Day5 从顺序表中删除其值在给定值s与t之间(包含s和t,要求s<t)的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退出执行。(类比Day4)
- Day6 从有序表中删除所有其值重复的元素,使表中所有元素的值均不同。
- Day7 已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,a3,...,am)和(b1,b2,b3,...,bn)。试编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2,b3,...,bn)放在(a1,a2,a3,...,am)的前面。
- Day8 将n(n > 1)个整数存放到一维数组R中,设计一个在时间和空间两方面都尽可能高效的算法,将R中保存的序列循环左移P (0<p<n)个位置,即将R中的数据由(X0,X1,...Xn-1)变成(Xp,Xp+1,...,Xn,X0,X1,...Xp-1),
前言
本文部分整理自up主 计算机考研大师兄,仅留作个人学习记录,侵删。
目录
Day1 在头结点的单链表L中,删除所有值为x的结点,并释放其空间。假设值为x的结点不唯一,试编写算法以实现上述操作。
void Del_x(LinkList &L, ElemType x){ //改变表的结构需要加取地址符&
LNode *p = L->next, *pre = L, *q;
while(p != NULL){ //表不为空
if(p->data == x){
q = p;
p = p->next;
pre->next = p;
free(q);
}else{
pre = p;
p = p->next;
}
}
}
Day2 将两个有序顺序表合并为一个新的有序顺序表,并由函数返回结果顺序表。
bool Merge(SqList A, SqList B, SqList &C){
if(A.length + B.length > C.MaxSize)
return false;
int i = 0, j = 0, k = 0;
while(i < A.length && j < B.length){
if(A.data[i] < B.data[j]){
C.data[k] = A.data[i];
i++, k++;
}else{
C.data[k] = B.data[j];
j++, k++;
}
}
while(i < A.length) //A表未空
C.data[k++] = A.data[i++];
while(i < B.length) //B表未空
C.data[k++] = B.data[j++];
C.length = k;
return true;
}
Day3 设计一个高效算法,将顺序表L的所有元素逆置,要求算法的空间复杂度为O(1)。
- 常规算法
void Reverse(SqList &L){
ElemType temp;
for(i = 0; i < L.length/2; i++){
temp = L.data[i];
L.data[i] = L.data[L.length-i-1];
L.data[L.length-i-1] = temp;
}
}
- 递归算法
void Reverse(int *A, int low, int high){
if(low < high){
swap(A[low], A[high]);
Reverse(A.low+1, A.high-1);
}
}
Day4 对长度为n的顺序表L,编写一个时间复杂度为O(n),空间复杂度为O(1)的算法,该算法删除线性表中所有值为x的数据元素。(类比Day1)
分析:时间复杂度O(n):扫描一次顺序表
空间复杂度O(1):申请常数个辅助空间
解法1
算法思想:扫描顺序表,记录其中x的个数k,将其中不为x的元素前移k个单位
void Del_x(SqList &L, ElemType x){
int k = 0, i=0;
while(i < L.length){
if(L.data[i] == x)
k++; //记数
else
L.data[i-k] = L.data[i]; //元素前移
i++;
}
L.length = L.length-k;
}
解法2
void Del_x(SqList &L, ElemType x){
int k = 0, i=0;
for(i = 0; i < L.length; i++){ //遍历
if(L.data[i] != x){
L.data[k] = L.data[i];
k++; //k是保留x的个数
}
L.length = k;
}
}
Day5 从顺序表中删除其值在给定值s与t之间(包含s和t,要求s<t)的所有元素,如果s或t不合理或顺序表为空,则显示出错信息并退出执行。(类比Day4)
bool Del_s_t(SqList &L, ElemType s, ElemType t){
int i = 0, k = 0;
if(L.length == 0 || s >= t)
return false;
for(i = 0; i < L.length; i++){
if(L.data[i] >= s && L.data[i] <= t)
k++;
else
L.data[i-k] = data[i];
}
L.length = L.length-k;
return true;
}
Day6 从有序表中删除所有其值重复的元素,使表中所有元素的值均不同。
算法思想:(第一个元素必然不会重复)从第一个元素依次向后扫描,重复的元素删除,不重复的元素保留。
bool Del_same(SqList &L){ //本题也可以不用布尔
if(L.length == 0)
return false;
for(i = 0, j = 1; j < L.length; j++) //i指向第一个元素,j指向第二个元素
if(L.data[i] != L.data[j])
L.data[++i] = L.data[i]; //将不重复的删除。
//上一步也可写两步,先++i,再[i]=[j]
L.length = i+1; //i的下标从0开始
return true;
}
Day7 已知在一维数组A[m+n]中依次存放两个线性表(a1,a2,a3,…,am)和(b1,b2,b3,…,bn)。试编写一个函数,将数组中两个顺序表的位置互换,即将(b1,b2,b3,…,bn)放在(a1,a2,a3,…,am)的前面。
分析:三次逆置
①(a1,a2,a3,…,am)逆置
②(b1,b2,b3,…,bn)逆置
③ 从0到n-1逆置
void Reverse(DataType A[], int left, int right){ //逆置算法
int mid = (left + right)/2;
int temp;
for(int i = 0; i < mid; i++){
temp = A[i];
A[i] = A[left + right -i];
A[left + right -i] = temp;
}
}
void Exchange(DataType A[], int m, int n){
Reverse(A, 0, m-1); //前m项逆置
Reverse(A, m, m+n-1); //后n项逆置
Reverse(A, 0, m+n-1); //整体逆置
}
Day8 将n(n > 1)个整数存放到一维数组R中,设计一个在时间和空间两方面都尽可能高效的算法,将R中保存的序列循环左移P (0<p<n)个位置,即将R中的数据由(X0,X1,…Xn-1)变成(Xp,Xp+1,…,Xn,X0,X1,…Xp-1),
要求:(1)给出算法的基本设计思想。
(2)根据设计思想,采用C或C++描述,关键之处给出注释。
(3)说明你所设计算法的时间复杂度和空间复杂度。
分析:三次逆置(类比Day7)
答:
(1)设计思想:
① 将(X0…Xp-1)逆置
②将(Xp…Xn-1)逆置
③整体逆置
(2)代码
void Reverse(DataType A[], int left, int right){ //逆置算法
int mid = (left + right)/2;
int temp;
for(int i = 0; i < mid; i++){
temp = A[i];
A[i] = A[left + right -i];
A[left + right -i] = temp;
}
}
void Exchange(DataType A[], int p, int n){
Reverse(A, 0, p-1); //前p项逆置
Reverse(A, p, n-1); //后n-p项逆置
Reverse(A, 0, n-1); //整体逆置
}
(3)时间复杂度O(n)
空间复杂度O(1)