顺序表的基本操作:
1.头文件 SqList.h
#ifndef CSqList_1
#define CSqList_1
#define MaxSize 50
typedef struct{ //结构体
int elem[MaxSize];
int length;
}SqList;
bool InitList(SqList &L); //初始化表,构造一个空表
int Length(SqList L); //求表长
int LocateElem(SqList L,int e); //按值查找,找到则返回值的数组下标
int GetElem(SqList L,int i); //按位查找,找到则返回值
bool ListInsert(SqList &L,int i,int e); //插入
bool ListDelete(SqList &L,int i); //删除
void PrintList(SqList L); //输出表的所有元素
bool Empty(SqList L); //判断表是否为空
bool DestroyList(SqList &L); //销毁表
bool Del_Min(SqList &L,int &value);//1.删除最小元素
bool Reverse(SqList &L); //2.将顺序表所有元素逆置, 空间复杂度为O(1)
bool Del_Elem(SqList &L,int x); //3.删除元素e
bool Del_Oder_Str_Elem(SqList &L,int s,int t); //4.从有序顺序表中删除s t之间的所有元素
bool Del_Str_Elem2(SqList &L,int s,int t);//5.删除线性表中 s t之间的元素
bool Del_Oder_Equal_Elem(SqList &L); //6.删除 有序表 中的重复元素
//bool Del_Hash_Equal_Elem(SqList &L); //6.2删除线性表中重复的元素
bool Merge(SqList A,SqList B,SqList &C); //7.合并有序表
void ReverseArr(int A[],int left,int right,int arraySize); //8.将一维数组的线性表逆置
void Exchange(int A[],int m,int n,int arraySize);
void SearchExchangeInsert(int A[],int n,int x); //9.二分查找顺序表
void HalfSearch(int A[],int n,int x); //二分查找
void Swap(int &A,int &B); //交换函数
void Insert(int A[],int n,int pos,int x); //插入 数组 数组大小 位置 插入的值
void MoveArr(int A[],int p,int n); //10.循环移动 A为要移动的数组,左移p个位置
void ReverseA(int A[],int from,int to);
int M_Search(int A[],int B[],int n); //11.查找两个升序序列的中位数
int Majority(int A[],int n); //12.查找主元素
#endif // CSqList_1
2.SqList.cpp
#include<iostream>
#include "CSqList.h"
//初始化表,构造一个空表
bool InitList(SqList &L){
L.length=0;
return true;
}
//求表长
int Length(SqList L){
return L.length;
}
//按值查找,返回值的元素所在的位置
int LocateElem(SqList L,int e){
for(int i=0;i<L.length;i++)
{
if(L.elem[i]==e)
return i+1;
}
return 0;
}
//按位查找,找到则返回值
int GetElem(SqList L,int i){
if(!L.length) //表为空,退出
return 0;
return L.elem[i];
}
//插入
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.elem[j]=L.elem[j-1]; //后移动元素
}
L.elem[i-1]=e;
L.length++;
return true;
}
//删除
bool ListDelete(SqList &L,int i){
if(i<1||i>L.length) //删除位置有误
{
return false;
}
for(int j=i;j<L.length;j++)
{
L.elem[j-1]=L.elem[j]; //前移元素
}
L.length--;
return true;
}
//输出表的所有元素
void PrintList(SqList L){
for(int i=0;i<L.length;i++)
{
std::cout<<"elem["<<i<<"]="<<L.elem[i]<<"\n";
}
}
bool Empty(SqList L){ //判断表四否为空
if(!L.length)
return true;
return false;
}
//1.删除表中具有最小值的元素(假设值唯一并由函数返回被删元素的值)空出的位置由后一个元素填补,若顺序表为空则显示出错误信息
bool Del_Min(SqList &L,int &value)
{
if(L.length==0) //顺序表长度为0,输出错误提示
{
std::cout<<"ListLink is NULL";
return false;
}
int pos=0; //数组下标从0开始
value=L.elem[pos]; //将第一个值给value
for(int i=1;i<L.length;i++) //把小于value的值给value并记住下标
{
if(L.elem[i]<value)
{
value=L.elem[i];
pos=i;
}
}
L.elem[pos]=L.elem[L.length-1];
L.length--;
return true;
}
//2.将顺序表中的所有元素逆置,要求空间复杂度为O(1)
bool Reverse(SqList &L)
{
if(L.length==0)
return false;
int temp;
for(int i=0;i<L.length/2;i++) //逆置换
{
temp=L.elem[i];
L.elem[i]=L.elem[L.length-1-i];
L.elem[L.length-1-i]=temp;
}
return true;
}
//3.长度为N的顺序表L,编写一个实际复杂度为O(n),空间复杂度为O(1)的算法,删除所有为X的元素
bool Del_Elem(SqList &L,int x)
{
if(L.length==0)
return false;
int k=0; //k记录不与x相同的元素的个数
for(int i=0;i<L.length;i++)
{
if(L.elem[i]!=x) //将不与x相同的元素存入数组下标为k的数组中
{
L.elem[k]=L.elem[i];
k++;
}
}
L.length=k; //此处的k为数组下标加1
return true;
}
//4.从 有序表 中删除其值在给定的值s-t之间的所有元素
bool Del_Oder_Str_Elem(SqList &L,int s,int t)
{
int i,j; //用i来寻找s,j来寻找t
if(s>=t||L.length==0)
{
return false;
}
for(i=0;i<L.length&&L.elem[i]<=s;i++); //找到s
if(i>=L.length) //判断s的位置是否合法
{
return false;
}
for(j=0;j<L.length&&L.elem[j]<t;j++);//找到t
for(;j<L.length;i++,j++) //有空缺则前移填补
L.elem[i]=L.elem[j];
L.length=i; //此时i是加1才跳出循环,不用加1
return true;
}
//5.从 线性表 中删除其值在给定的值s-t之间的所有元素
bool Del_Str_Elem2(SqList &L,int s,int t)
{
if(s>=t||L.length==0)
{
return false;
}
int k=0; //t统计不再s t 之间的数 并充当数组下标
for(int i=0;i<L.length;i++) //找到s
{
if(L.elem[i]>t||L.elem[i]<s)
{
L.elem[k]=L.elem[i]; //统计不再s t 之间的数的个数,并依次向前赋值
k++;
}
}
L.length=k;
return true;
}
//6.从有序表中删除值重复的数
bool Del_Oder_Equal_Elem(SqList &L)
{
if(L.length==0)
return false;
int i,k=0;
for(i=1;i<L.length;i++)
{
if(L.elem[i]!=L.elem[i-1]) //判断是否重复
{
L.elem[++k]=L.elem[i]; //没有重复就向前赋值
}
}
L.length=k+1; //此处的k为数组下标 所有加1
return true;
}
//7.合并两个 有序表
bool Merge(SqList A,SqList B,SqList &C)
{
if(A.length+B.length>MaxSize) //大于顺序表的长度则返回false
return false;
int i=0,j=0,k=0;
while(i<A.length&&j<B.length) /*循环,两两比较,小者存入结果表*/
{
if(A.elem[i]<=B.elem[j])
{
C.elem[k++]=A.elem[i++];
}
else
{
C.elem[k++]=B.elem[j++];
}
}
//还剩一个没有比较完的顺序表
while(i<A.length)
{
C.elem[k++]=A.elem[i++];
}
while(j<B.length)
{
C.elem[k++]=B.elem[j++];
}
C.length=k;
return true;
}
//8.逆置一维数组里的线性表(多函数实现)
void ReverseArr(int A[],int left,int right,int arraySize) //left是m的长度 right是n的长度
{
if(left>=right||right>=arraySize) //逆置首尾位置合法判断
return ;
int mid=(left+right)/2; //折半逆置
for(int i=0;i<=mid-left;i++)
{
Swap(A[left+i],A[right-i]);
}
}
void Exchange(int A[],int m,int n,int arraySize) //调用三次逆置函数交换
{
ReverseArr(A,0,m+n-1,arraySize);
ReverseArr(A,0,n-1,arraySize);
ReverseArr(A,n,m+n-1,arraySize);
}
//9.二分查找
void SearchExchangeInsert(int A[],int n,int x) //A是数组,n是数组内元素个数,x是查找的数
{
int mid,low=0,high=n-1,i; //low and high 指向顺序表的下界和上界的下标
while(low<=high){
mid=(low+high)/2; //找到中间位置
if(A[mid]==x)break; //找到x 退出while循环
else if(A[mid]<x)low=mid+1; //到中间点的右半部去查
else high=mid-1; //到中间点的左半部去查
}
//下面两个if只会执行一个
if(A[mid]==x&&mid!=n-1) //若最后一个元素与X相等,则不存在与其后继交换的操作
{
int temp=A[mid];
A[mid]=A[mid+1];
A[mid+1]=temp;
}
if(low>high) //查找失败
{
for(i=n-1;i>high;i--) //后移
{
A[i+1]=A[i];
}
A[i+1]=x; //插入
}
}
//二分查找,在有序序列中
void HalfSearch(int A[],int n,int x) //由于数组传递的是地址,等同于交换函数的引用符号
{
int mid,low=0,high=n-1; //low and high ,mid指向顺序表的下界和上界和中部的下标
while(low<=high)
{
mid=(low+high)/2;
if(A[mid]==x)break;
else if(A[mid]>x)high=mid-1;
else low=mid+1;
}
if(A[mid]==x&&mid!=n-1)
{
Swap(A[mid],A[mid+1]);
}
if(low>high)
{
Insert(A,n,high,x);
}
}
//交换函数
void Swap(int &A,int &B)
{
int temp=A;
A=B;
B=temp;
}
//数组插入函数
void Insert(int A[],int n,int pos,int x)
{
for(int i=n-1;i>pos;i--)
A[i+1]=A[i];
A[pos+1]=x;
}
//10.数组A内的元素循环移动p个位置
void MoveArr(int A[],int p,int n)
{
ReverseA(A,0,p-1);
ReverseA(A,p,n-1);
ReverseA(A,0,n-1);
}
//倒置函数
void ReverseA(int A[],int from,int to)
{
int i;
for(i=0;i<(to-from+1)/2;i++)
{
Swap(A[from+i],A[to-i]);
}
}
//查找两个升序序列的中位数
int M_Search(int A[],int B[],int n) //升序表A 升序表B 和表等长n
{
int s1=0,d1=n-1,m1,s2=0,d2=n-1,m2; //分别为升序序列的首位数,尾位数,中位数
while(s1!=d1||s2!=d2)
{
m1=(s1+d1)/2; //A中位数(下标)
m2=(s2+d2)/2; //B中位数(下标)
if(A[m1]==B[m2])
return A[m1];
if(A[m1]<B[m2]) //如果序列A中位数小于序列B中位数
{
if((s1+d1)%2==0) //元素个数为奇数
{
s1=m1; //舍去A的中间点前的全部元素且保留中间点
d2=m2; //舍去B的中间点后的全部元素且保留中间点
}
else
{
s1=m1+1; //舍去A的中间点以及中间点前的全部元素
d2=m2; //舍去B的中间点后的全部元素且保留中间点
}
}
else
{
if((s2+d2)%2==0) //元素个数为奇数
{
s2=m2; //舍去B的中间点前的全部元素且保留中间点
d1=m1; //舍去A的中间点后的全部元素且保留中间点
}
else
{
s2=m2+1; //舍去B的中间点以及中间点前的全部元素
d1=m1; //舍去A的中间点后的全部元素且保留中间点
}
}
}
return A[m1]<B[m2]?A[m1]:B[m2];
}
//12.查找主元素
int Majority(int A[],int n)
{
int i,c,count=1; //c保存候选主元素,count统计次数
c=A[0]; //初始设A[0]为候选主元素
for(i=1;i<n;i++)//遍历
{
if(A[i]==c) //对候选主元素加1
{
count++;
}
else
{
if(count>0) //处理的不是候选主元素
{
count--;
}
else
{
c=A[i]; //更换候选主元素
count=1;
}
}
}
if(count>0) //判断有没有候选主元素的可能
{
for(i=count=0;i<n;i++) //统计候选主元素实际出现的次数
{
if(A[i]==c)
{
count++;
}
}
}
if(count>n/2)return c;
else return -1;
}