线性表综合应用题

题一

int combine(int A[],int &a,int B[],int b)   //因为合并后a改变了长度,所以使用引用型&
{
    //先写溢出情况(假设返回-1)
    if(a+b>maxSize)
        return -1;
    
    //写成功合并的方法
    int i=a,j=b;
    while(j>0)
    {
        if(i==0||A[i-1]<B[j-1])    //从最后一个元素向前比较
        {
            A[j+i-1]=B[j-1];   //将B[]较大的元素先定位到A[]里,此时B[j-1]为第i+j大的元素
            --j;
        }
        else
        {
            A[j+i-1]=A[i-1];	//此时A[i-1]为第i+j大的元素
            --i;
        }
    }
    a=a+b;
    return a;
}

题二

int compare(int A[],int a,int B[],int b)
{
    int i=0,j=0;    //指针作用
    
    //相同部分
    while(i<a&&j<b&&A[i++]=B[j++])
        --i;
        --j;
    
    if(i==a&&j==b)
        return 0;
    if(i==a&&j!=b)
        return -1;
    if(i!=a&&j==b)
        return 1;
    if(A[i]>B[j])
        return 1;
    else
        return -1;   //A[i]<B[i]
}

题三

int Combine(int lists[][maxSize],int lens[],int m)
{
    int flag;
    for(int i=1;i<m;i++)   
    {	//调用题一写过的combine方法
        flag=combine(lists[0],lens[0],lists[i],lens[i]);   //lens[i]为i行表的长度
        if(flag==-1)   //失败
            break;
    }
    return flag;	  //成功
}

题四

//递增,A∩B=C; 时间复杂度0(a+b),a、b为顺序表长度(元素个数) 
int intersect(int A[],int a,int B[],int b,int C[],int &c)
{
    //溢出情况
    if(a+b>maxSize)
        return -1;
    
    int i=a,j=b,k;			//从最后一个元素向前比较
    while(i>=0&&j>=0)     
    {
        if(A[i]>B[j])
            --i;
        if(A[i]<B[j])
            --j;
        else      //A[i]=B[j]就要并入C[]
        {
            C[k++]=A[i];
            --i;
            --j;
        }
    }
    c=k;
    return c;
}

题五

//非递减,A∪B=C;
//难点在于对重复元素的处理
int union(int A[],int a,int B[],int b,int C[],int &c)
{
    int i=0,j=0,k=0;
    
    //溢出情况
    if(a+b>maxSize)   //maxSize(已定义)应是数组C长度
        return -1;
    
    while(i<a&&j<b)
    {
        if(A[i]<B[j])
        {	//注意k=0的判断,因为A、B可能是空表
            //注意k>0的判断,C[k-1]溢出
            if(k>0)
            {
                if(C[k-1]!=A[i])   //过滤相同元素
                    C[k++]=A[i++];
                else
                    ++i;
            }
            else
                C[k++]=A[i++];
        }
        else
        {
            if(k>0)
            {
                if(C[k-1]!=B[j])   //过滤相同元素
                    C[k++]=B[j++];
                else
                    ++j;
            }
            else
                C[k++]=B[j++];
        }
    }
    while(i<a)
    {
        if(k>0)
        {
            if(C[k-1]!=A[i])
                C[k++]=A[i++];
            else
                ++i;
        }
        else
            C[k++]=A[i++];
    }
	while(j<b)
    {
        if(k>0)
        {
            if(C[k-1]!=C[j])
                C[k++]=B[j++];
            else
                ++j;
        }
        else
            C[k++]=B[j++];
    }
    c=k;
    return c;
}

题六

void reverse(LinkNode *&h)
{
    //该单链表没有头结点,h直接指向首节点
    //逆转之后,h指向尾结点,使其成为首节点
    //空的情况
    if(h==NULL)
        return;
    
    LinkNode *p=h->next,*q=NULL;
    while(p!=NULL)
    {
        h->next=q;   //逆转h指针
        //指针前移
        q=h;
        h=p;
        p=p>next;
    }
    h->next=q;
}

题七

void separate(LinkNode *&A,LinkNode *&B,LinkNode *&C)
{
    //假设A为初始单链表,分离后,A(数字)、B(字母)、C(其他)
    LinkNode *pa,*pb,*pc,*p=A->next;
    //pa,pb,pc分别是3个结果链表的链尾指针,初始时指向各表头
    pa=A;
    pb=B=(LinkNode *)malloc(sizeof(LinkNode));
    pc=C=(LinkNode *)malloc(sizeof(LinkNode));
    while(p!=NULL)
    {
        //此处书上运用了ctype.h函数库,人生苦短,能简就简
        if(isdigit(p->data))   //数字字符,链入数字链
            //if(p->data>='0'&&p->data<='9')
        {
            pa->next=p;
            pa=p;
        }
    	else if(isalpha(p->data))   //字母字符,链入字母链
            //if((p->data>='a'&&p->data<='z')||(p->data>='A'&&p->data<='Z'))
        {
            pb->next=p;
            pb=p;
        }
    	else   					//其他字符,链入其他链
        {
            pc->next=p;
            pc=p;
        }
    	p=p->next;
    }
    pa->next=NULL;
    pb->next=NULL;
    pc->next=NULL;   //尾域置空
}

题八

void insert(int S[],int &m,int L[],int R[],int n,int i,int j,int x)   //m随插入元素而改变
{
    //溢出情况
    if(R[n]==m)
        return;
    
    else
    {
        int p=L[i]+j;   //确定S[]中的插入位置p
        int k;
        for(k=m-1;k>=p;--k)   //将p及以后元素全部后移一位
            S[k+1]=S[k];
        S[k+1]=x;   //插入元素
        ++m;       //所有表总长度+1
        //将线性表范围标记L[]、R[]做修改
        ++R[i];
        for(k=i+1;k<=n;++k)
        {
            ++L[k];
            ++R[k];
        }
    }
}
void delete(int S[],int &m,int L[],int R[],int n,int i,int j)
{
    int p=L[i]+j-1;   //确定S[]中的删除位置p
    int k;
    for(k=p;k<m-1;++k)   //将p及以后元素全部前移一位
        S[k]=S[k+1];
    --m;   //所有表总长度-1
     //将线性表范围标记L[]、R[]做修改
    --R[i];
    for(k=i+1;k<=n;++k)
    {
        --L[k];
        --R[k];
    }
}

题九

//对顺序表先整体逆转,然后子表分别逆转
void reverse(int A[],int L,int R)
{
    int i=L,j=R;
    while(i<j)
    {
        int temp=A[i];
        A[i]=A[j];
        A[j]=temp;
        ++i;
        --j;
    }
}
void exchange(int A[],int m,int n)
{
    //数组A[m+n],0~m-1存子表a,m~m+n-1存子表b,交换子表位置
    reverse(A,0,m+n-1);    //(bn,bn-1,...,am,am-1,..,a1)
    reverse(A,0,n-1);     //(b1,b2,...,bn,am,am-1,..,a1)
    reverse(A,n,m+n-1);  //(b1,b2,...,bn,a1,a2,...,am)
}

题十

void move(int A[],int n)
{
    int p=0;
    for(int i=0,i<n;i++)
    {
        if(A[i]!=0)
        {
            if(i!=p)   //前移非0元素
            {
                A[p]=A[i];
                A[i]=0;
            }
            ++p;
        }
    }
}

题十一

//(1)求链表中最大整数
int getMax(LinkNode *L)
{
    //非空,仅一个元素
    if(L->next==NULL)
        return L->data;
    int temp=getMax(L->next);   //递归求最大值
    if(L->data>temp)
        return L->data;
    else
        return temp;
}

//(2)求链表的结点个数
int getNum(LinkNode *L)
{
    //非空,仅一个元素
    if(L->next==NULL)
        return 1;
    return 1+getNum(L->next);   //递归求个数
}

//(3)求所有整数平均值
float getAvg(LinkNode *L,int n)
{
    //非空,仅一个元素
    if(L->next==NULL)
        return (float)(L->data);
    else
    {
        float sum=getAvg(L->next,n-1)*(n-1);   //求后面n-1个元素和
        return (float)(L->data+sum)/n;        //加上首节点求平均值
    }
}

题十二

//同李春葆数据结构课后习题16,并没完全看懂他的解答,这里深层分析一下
//①正向搜索寻找满足要求的结点
//②把该结点从链中摘下
//③反向根据访问计数寻找插入位置
//④把该结点重新插入到链表
DLinkNode *locate(DLinkNode *&DL,int x)
{
    DLinkNode *p=DL->next,*q;
    while(p!=NULL&&p->data!=x)
        p=p->next;
    if(p!=NULL)
    {	
        //结点访问频度+1
        ++(p->freg);
        q=p;
        //从链表摘下这个结点
        q->prior->next=q->next;
        q->next->prior=q->prior;
        //寻找重新插入位置
        p=q->prior;
        while(p!=DL&&q->freq>p->freq)
            p=p->prior;
        //插在p后
        q->next=p->next;
        q->prior=p;
        p->next->prior=q;
        p->next=q;
        return q;
    }
    else
        return NULL;   //没找到
}
posted @ 2020-05-28 11:05  我在吃大西瓜呢  阅读(259)  评论(0编辑  收藏  举报