考研408数据结构线性表复习
有任何问题请私信
#include<iostream>
#include<algorithm>
const int initlength = 100; ///顺序表的初始长度
using namespace std;
typedef struct
{
int *data;
int MaxSize, length; ///顺序表的最大存储空间,长度;
}SeqList;
///*****顺序表基本操作
void initList(SeqList &L, int n = initlength) ///初始化顺序表
{
L.data = new int [n];
L.length = 0;
L.MaxSize = n;
for(int i=0;i<L.MaxSize;++i)
{
cin>>L.data[i];
L.length++;
}
}
int Length(SeqList L) ///返回顺序表的长度
{
return L.length;
}
bool EmptyList(SeqList L) ///判断顺序表是否为空
{
if(L.length == 0)
return true;
return false;
}
bool ListInsert(SeqList &L, int i, int value) ///插入元素, i为元素的位置, value为元素的值
{
if(i<1 || i>L.length+1)
return false;
if(i >= L.MaxSize)
return false;
for(int j=L.length; j>=i; --j)
L.data[j] = L.data[j-1];
L.data[i-1] = value;
L.length++;
return true;
}
bool ListDelete(SeqList &L, int i, int &e) ///删除元素, i为删除元素的位置, e为删除位置元素的值
{
if(i<1 || i>L.length)
return false;
e = L.data[i-1];
for(int j=i-1; j<L.length-1; ++j)
L.data[j] = L.data[j+1];
L.length--;
return true;
}
int LocateElem(SeqList L, int e) ///按值查找第一个元素值为e的位序
{
for(int i=0; i<L.length; ++i)
{
if(e == L.data[i])
return i+1;
}
return 0;
}
void PrintList(SeqList L) ///打印输出整个顺序表
{
for(int i=0;i<L.length;++i)
cout<<L.data[i]<<" ";
cout<<endl;
}
///***顺序表进阶操作,带题目描述
///1.在顺序表中删除具有最小值的元素(假设唯一), 并由函数返回被删元素的值
/// 空出的位置由最后一个元素填补。若顺序表为空,显示错误信息并退出
bool DeleteMinList(SeqList &L, int &e)
{
if(EmptyList(L)) //if (L.length == 0)
{
cout<<"The List is empty, can't delete the min value!"<<endl;
return false;
}
int ListMin = L.data[0];
int LocalMin = 0;
for(int i=0;i<L.length;++i)
{
if(ListMin > L.data[i])
{
ListMin = L.data[i];
LocalMin = i;
}
}
e = ListMin;
L.data[LocalMin] = L.data[L.length-1];
L.length--;
return true;
}
///2.设计一个高效算法,将顺序表的所有元素逆置,要求算法的空间复杂度为O(1)
void ReverseList(SeqList &L)
{
int temp;
for(int 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;
}
}
///3.长度为n的顺序表L, 编写一个时间复杂度为O(n), 空间复杂度为O(1), 该算法删除线性表中所有值为x的数据元素。
///可为该顺序表重新构造
void DeleteEqualElement(SeqList &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;
}
///或者第二种算法
/*
void DeleteEqualElement(SeqList &L, int 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 -= k;
}
*/
///4.从有序顺序表中删除其值在给定值s与t之间(要求s<t)的所有元素,如果s或t不合理或者顺序表为空则显示出错信息并退出运行。
/*
bool Delete_s_among_t(SeqList &L, int s, int t) ///调用此函数前请使用sort或者自定义算法对顺序表排序,使之成为有序表
{
if(s>=t || EmptyList(L))
{
cout<<"The function is not exploit,please check your input or if the list is empty.";
return false;
}
int k=0;
int num=0;
for(int i=0;i<L.length;++i)
{
if(L.data[i] > s && L.data[i] < t)
{
num++;
if(num == 1)
k = i;
}
}
if(num == 0)
return false;
for(int i=k;i<L.length-num;++i)
{
L.data[i] = L.data[i+num];
}
L.length -= num;
return true;
}
*/
///王道给出标准算法
bool Delete_s_among_t(SeqList &L, int s, int t)
{
if(s>=t || EmptyList(L))
{
return false;
}
int i, j;
for(i=0; i<L.length&&L.data[i]<s; i++)
if(i >= L.length)
return false;
for(j=i; j<L.length&&L.data[j]<=t; j++){}
for(;j<L.length; i++, j++)
L.data[i] = L.data[j];
L.length = i+1;
return true;
}
///5.从顺序表中删除其值在给定值s与t之间(包含s和t, 要求s<t)的所有元素,如果s或t不合理或者顺序表为空则显示错误信息并退出运行。
/*
bool Delete_s_among_t2(SeqList &L, int s, int t)
{
if(s>=t || EmptyList(L))
{
cout<<"The function is not exploit,please check your input or if the list is empty."<<endl;
return false;
}
bool flag = false;
for(int i=0;i<L.length;++i)
{
if(L.data[i]>=s && L.data[i] <= t)
{
for(int j=i;j<L.length-1;++j)
L.data[j] = L.data[j+1];
L.length--;
flag = true;
--i;
}
}
return flag;
}
*/
///王道推荐高效算法
bool Delete_s_among_t2(SeqList &L, int s, int t)
{
if(s>=t || EmptyList(L))
{
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 -= k;
return true;
}
///6.从有序顺序表中删除所有其值重复的元素,使表中所有元素的值均不同
bool Delete_repeat_value(SeqList &L)
{
if(EmptyList(L))
return false;
int i, j;
for(i=0, j=1;j<L.length;++j)
{
if(L.data[i]!=L.data[j])
L.data[++i] = L.data[j];
}
L.length = i+1;
return true;
}
///7.将两个有序顺序表合并成一个有序顺序表,并由函数返回结果顺序表。
SeqList combine_List(SeqList L1, SeqList L2, SeqList &L3)
{
///加层判断,若L3最大存储空间小于L1+L2的长度,则返回
int i=0, j=0, k=0;
while(i<L1.length && j<L2.length)
{
if(L1.data[i] < L2.data[j])
{
L3.data[k++] = L1.data[i++];
}
else
{
L3.data[k++] = L2.data[j++];
}
}
while(i<L1.length)
L3.data[k++] = L1.data[i++];
while(j<L2.length)
L3.data[k++] = L2.data[j++];
L3.length = k;
return L3;
}
///8.已知在一维数组A[m+n]中依次存放着两个线性表,试编写一个函数,将数组中两个顺序表的位置互换,即将bn放在an前面
void reverse_list(SeqList &L, int n)
{
int mid = (L.length)/2;
for(int i=0;i<mid;++i)
{
int t = L.data[i];
L.data[i] = L.data[L.length-i-1];
L.data[L.length-i-1] = t;
}
mid = (L.length-n)/2;
for(int i=0; i<mid; ++i)
{
int t = L.data[i];
L.data[i] = L.data[L.length-n-i-1];
L.data[L.length-n-i-1] = t;
}
mid = n/2;
for(int i=0; i<n/2; ++i)
{
int t = L.data[L.length-n+i];
L.data[L.length-n+i] = L.data[L.length-i-1];
L.data[L.length-i-1] = t;
}
}
///王道推荐算法,由两个函数构成 个人略微调整了一下
void Reverse_list(SeqList &L, int left, int right) ///该函数用于进行逆置
{
if(left >= right || right >= L.length)
return;
int mid = (left + right)/2;
for(int i=0;i<=mid-left;++i)
{
int t = L.data[left + i];
L.data[left+i] = L.data[right-i];
L.data[right-i] = t;
}
//PrintList(L);
}
void Exchange(SeqList &L, int n)
{
Reverse_list(L, 0, L.length-1);
Reverse_list(L, 0, L.length-n-1);
Reverse_list(L, L.length-n, L.length-1);
}
///9.线性表中元素递增有序且按照顺序存储于计算机内,要求设计一算法完成用最少时间在表中查找数值为x的元素,
///若找到后将其与后继元素位置相交换,若找不到则将其插入表中并使表中元素仍递增有序。
void mid_find(SeqList &L, int l, int r, int key) ///查找算法采取二分
{
if(l >= r)
return;
int mid;
while(l<=r)
{
mid = (l + r)/2;
if(L.data[mid] == key)
break;
///进行交换操作
else if(L.data[mid] > key)
r = mid - 1;
else
l = mid + 1;
}
//cout<<mid<<endl;
//cout<<l<<" "<<r<<endl;
if(L.data[mid] == key && mid != L.length-1)
{
int t = L.data[mid+1];
L.data[mid+1] = L.data[mid];
L.data[mid] = t;
}
if(l>r)
{
for(int i=L.length;i>l;--i)
L.data[i] = L.data[i-1];
L.data[l] = key;
L.length++;
}
}
///10.设将n个证书存放在一维数组R中,试实际一个在时间和空间两方面都尽可能高效的算法。
///将R中保存的序列循环左移p个位置,即将R中的数据由(X0, X1, ...Xn-1)变换为(Xp, Xp+1, ....Xn-1, X0, X1..., Xp-1)
///与8题相同思路
///11.一个长度为L的升序序列S, 处在第[L/2]个位置的数称为S的中位数。现在有两个等长序列A和B,
///试设计一个时间和空间都尽可能高效的算法,找出两个序列A和B的中位数
///算法描述:分别求两序列的中位数a和b。
///1.若a=b, 则结束,a或b即为所求中位数
///2.若a<b, 则舍弃A中较小一半,同时舍弃B中较大一半, 要求两次舍弃长度相等
///3.若a>b, 则舍弃A中较大一半,同时舍弃B中较小一半, 要求两次舍弃长度相等
///在保留的两个升序序列中,重复过程123, 知直到两个序列中只含一个元素为止, 较小者即为所求中位数
int M_search(SeqList &L1, SeqList &L2)
{
int s1=0, d1=L1.length-1, m1, s2=0, d2=L2.length-1, m2;
while(s1!=d1 || s2!=d2)
{
m1 = (s1+d1)/2;
m2 = (s2+d2)/2;
if(L1.data[m1] == L2.data[m2])
return L1.data[m1];
else if(L1.data[m1] > L2.data[m2])
{
if((s1+d1)%2 == 0)
{
d1 = m1;
s2 = m2;
}
else
{
d1 = m1;
s2 = m2+1;
}
}
else
{
if((s1+d1)%2 == 0)
{
s1 = m1;
d2 = m2;
}
else
{
s1 = m1 + 1;
d2 = m2;
}
}
}
return L1.data[s1]>L2.data[s2]? L2.data[s2]:L1.data[s1];
}
///12.已知一个整数序列,若存在m个相同元素(m>n/2),则称m为A中的主元素,若存在主元素,输出,不存在,输出-1
///王道推荐算法(本人首先想到哈希算法)
///查找出现次数最多的元素为难点
int Majority(SeqList &L)///查找可疑出现次数最多元素算法???
{
int c=L.data[0], num =1;
for(int i=1;i<L.length;++i)
{
if(L.data[i] == c)
num++;
else if(num > 0)
num--;
else
{
c = L.data[i];
num = 1;
}
}
num = 0;
for(int i=0;i<L.length;++i)
if(c == L.data[i])
num++;
if(num > L.length/2)
return c;
else
return -1;
}
int main()
{
ios::sync_with_stdio(false);
SeqList L;
int n;
cin>>n;
initList(L, n);
/*
initList(L1, n);
cin>>m;
initList(L2, m);
ListInsert(L, 5, 8);
PrintList(L);
cout<<"The List Length is "<<Length(L)<<endl;
int e;
ListDelete(L, 5, e);
PrintList(L);
cout<<"e's value is "<<e<<endl;
cout<<"The List Length is "<<Length(L)<<endl;
int order = LocateElem(L, 6);
if(order != 0)
cout<<"The element's order is "<<order<<endl;
else
cout<<"sorry, we can't find the value's order!!!"<<endl;
DeleteMinList(L, e);
PrintList(L);
cout<<"e's value is "<<e<<endl;
ReverseList(L);
PrintList(L);
Delete_s_among_t2(L, 6, 9);
PrintList(L);
L3 = combine_List(L1, L2, L3);
PrintList(L3);
cout<<L3.length<<endl;
//reverse_list(L3, 2);
Exchange(L3, 2);
PrintList(L3);
mid_find(L, 0, L.length-1, 5);
PrintList(L);
cout<<M_search(L1, L2)<<endl;*/
cout<<Majority(L)<<endl;
return 0;
}