数据结构基础—顺序表的基本操作(数据结构学习总结)

顺序表的基本操作:

  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;
}

猜你喜欢

转载自blog.csdn.net/qq_36018710/article/details/81148004
今日推荐