线性表-LinkList(单链表练习题)

typedef struct Nodel
{
    int a;
    struct Nodel* next;
}node;
node *head1;head1->next=NUll;
node *end1=NULL;

 

1:在带头结点的单链表L中插入尾结点

复制代码
void add(int value)
{
    node *p;
    p=(node *)malloc(sizeof(node));
    p->a=value;
    p->next=NULL;

    if(head->next==NULL)//若头结点指向的第一个节点为空
    {
        head->next=p;
        end=p;
    }
    else
    {
        end->next=p;
        end=p;
    }


}
复制代码

2:在带头结点的单链表L中,删除所有值为X的节点,释放空间

复制代码
node *delX(int x)
{
    node *p,*pre,*cur;
    p=head;//指向头节点
    pre=p;//当前值的前一个 目前指向头结点
    while(pre->next!=NULL)
    {
        cur=pre->next;//当前值
        if(cur->a==x)
        {
           pre->next=cur->next; //删除当前值
           free(cur);//释放当前值,前一个位置不变 前一个指向的下一个值为当前值的下一个值
        }
        else
        {
            pre=pre->next;
        }
    }
    return p;
}
复制代码

3:L为头结点的单链表,从尾到头反向输出每个节点的值(递归调用)

复制代码
void printVert(node *q)
{
    if(q->next!=NULL)printVert(q->next);
    if(q!=NULL)printf("%d",q->a);
}
void printVertMain()
{
    node *p;
    p=head->next;
    if(p!=NULL)printVert(p->next);
}
复制代码

4:在带头结点的单链表L中删除一个最小值节点的高效算法//零时指针指向当前最小值,另一指针一直往前走

复制代码
void delMIn()
{
    node *pre,*curmin,*cur,*temp;
    cur=head;//指向第一个节点
    pre=head;
    curmin=cur->next;//把第一个节点当做当前最小点
    while(cur->next!=NULL)
    {

        temp=cur;
        cur=cur->next;
        if((cur->a)<(curmin->a))
        {
            pre=temp;
            curmin=cur;
        }

    }
    if(curmin!=NULL)
    {
        pre->next=curmin.next;
        free(curmin);
    }

}
复制代码

5:将带头结点的单链表就地逆转

   1:借助数组

复制代码
void curVert()
{
    node *p=head->next,*q;
    q=p;
    int arr[100];
    int i=0,j;
    while(p!=NULL)
    {
        arr[i]=p->a;
        p=p->next;
        i++;
    }
    for(j=i-1;j>=0;j--)
    {
        q->a=arr[j];
        q=q->next;
    }
}
复制代码

    2:将头节点摘下,放到尾结点

复制代码
void curVert()
{
    node *p=head,*q=end;
    while(p->next!=end)//p节点位置不变,到尾结点位置变成头结点的下一个位置为止
    {
        q=p->next;//头结点指向的节点放到end处
        p->next=p->next->next;//头结点指向下下个节点

q->next=NULL;//尾结点指向空节点 q=q->next; } }
复制代码

6:带头结点的单链表L设计一个算法使其元素递增有序

   1:数组存储元素,排序后重新赋值(不写了)

   2:直接插入排序(不怎么懂

复制代码
void Sort(LinkList &L){
    node *p=L->next, *pre;
    node *r=p->next;  //r保持*p后继结点指针,以保证不断链
    p->next=NULL;  //构造只含一个数据结点的有序表
    p=r;
    while(p!=NULL){
        r=p->next;  //保存*p的后继结点指针
        pre=L;
        while (pre->next!=NULL && pre->next->a<p->a)
            pre=pre->next;  //在有序表中查找插入的前驱结点*pre
        p->next=pre->next;  //将*p 插入到*pre 之后
        pre->next=p;
        p=r; //扫描原单链表中剩下的结点
    }
}
复制代码

 

7:设在一个带头结点的单链表中所有元素结点的数据值无序,试编写一个函数,删除表中所有介于给定的两个值

(作为函数参数给出)之间的元素的元素(若存在)。

复制代码
void delBet(int low,int up)
{
    node *p,*pre,*cur;
    p=head;
    while(p->next!=NULL)
    {
        cur=p->next;
        if(cur->a<up&&cur->a>low)
        {
            p->next=cur->next;
            free(cur);
        }else{
            p=p->next;
        }

    }
}
复制代码

8: 给定两个单链表,编写算法找出两个链表的公共结点

    1:我写的

复制代码
node searchCommon(node *A,node *B)
{
    node *p=A,*q=B;
    while(A->next!=NULL)
    {
        p=A->next;
        while(B->next!=NULL)
        {
            q=B->next;
            if(p==q)
            {
                printf("%d ",p->a);
return p;
} B=q; } A=p; } }
复制代码

   2:书上的(若有公共节点,则该节点之后的节点都是重合的,即最后的节点是重合的说明有公共节点)

复制代码
node searchCommon(node *n1,node *n2)
{
    int len1=Length(n1),len2=Length(n2);
    node longList,shortList;
    if(len1>len2)
    {
        longList=n1->next;shortList=n2->next;
        dist=len1-len2;//表长之差
    }
    else
    {
        longList=n2->next;;shortList=n1->next;
        dist=len2-len1;
    }
    while(dist--)//表长的链表先遍历到第dist个节点然后同步
    {
        longList=longList->next;
    }
    while(longList!=NULL)//同步寻找共同节点
    {
        if(longList==shortList)return longList;//找到第一个公共节点
        else//继续同步寻找
        {
            longList=longList->next;
            shortList=shortList->next;
        }
    }
    return NULL
}
复制代码

9.:给定一个带表头结点的单链表,设head为头指针,结点结构为(data,next),data为整型元素,
next 为指针,试写出算法:按递增次序输出单链表中各结点的数据元素,并释放结点所占的存储空间
(要求:不允许使用数组作为辅助空间),
//先找到最小值输出再删除节点

复制代码
void printandfree()
{
    node *p=head,*q,*pre,*cur;//q移动指针
    int min=p->next->a;//设为最小值
    while(p->next!=NUll)
    {
        q=p;//q位置初始化
        while(q->next!=NULL)//找当前序列最小值位置并记录值
        {
           if(q->next->a<min)//找到更小的
           {
               pre=q;
               cur=q->next;
               min=q->next->a;
           }
           q=q->next;
        }
        printf("%d ",min);
        pre->next=cur->next;//删除
        free(cur);
    }
    free(head);
}
复制代码

10:将一个带头结点的单链表A分解为两个带头节点的单链表A和B,使得A表中含有原表中序号为奇数的元素,
而B表中含有原表中序号为偶数的元素,且保持其相对顺序不变。//将a链表中偶数元素放到b链表并删除

复制代码
void seperate(node *A)
{
    node *p=A;
    node *B,*Bhead,*pre,*cur;
    Bhead=(node *)malloc(sizeof(node));
    B=Bhead;
    B->next=NULL;//B指向头结点
    while(p->next!=NULL)
    {
        pre=p;cur=p->next;
        if((cur->a)%2==0)
        {
            node *m=(node *)malloc(sizeof(node));
            m->a=cur->a;
            m->next=NULL;
            B->next=m;
            B=B->next;//B链表新增节点 B指向尾结点
            pre->next=cur->next;free(cur);//删除A链表偶数节点
            //p仍在原地
        }
        else
        {
           p=p->next;//p往前走一步
        }

    }
}
复制代码

11:设C={a1,b1,a2,b2,...an,bn}为线性表,采用带头结点的hc单链表存放,设计一个就地
算法,将其拆分为两个线性表,使得A= {a1,a2...an},B= {bn,...b2,b1}

复制代码
void seperate(node *hc)
{//放一个数组,存入表值,排序
    int arr[2n],i=0,k,m=0,n=0,m1=0;//i走了n之后停止
    int arra[n],arrb[n];
    node *p=hc->next,*q=p;
    while(p!=NULL)
    {
        arr[i++]=p->a;
        p=p->next;
    }
    for(k=0;k<i;k++)
    {
        arra[m++]=arr[k];
        k++:
        arrb[n++]=arr[k];
    }
    while(q!=NULL)
    {
        if(m1<m)
        {
            q->a=arra[m1++];
        }
        else
        {
            q->a=arrb[--n];
        }
        q=q->next;
    }
}
复制代码

12:在一个递增有序的线性表中,有数值相同的元素存在。若存储方式为单链表,设计算法
去掉数值相同的元素,使表中不再有重复的元素,例如(7, 10, 10, 21,30, 42, 42,42,51,70
将变为(7, 10, 21, 30, 42,51, 70)。

复制代码
void delrepeat()
{
   node *p=head,*pre,*cur;
   pre=p->next;//头结点
   while(pre->next!=NULL)
   {
       cur=pre->next;//pre是不重复的,cur是当前的,next是当前的下一个
       if(pre->a==cur->a)//如果跟前一个相同就删除
       {
           pre->next=cur->next;
           free(cur);
       }else
       {
           pre=pre->next;
       }
   }
}
复制代码

13:假设有两个按元素值递增次序排列的线性表带头结点,均以单链表形式存储。请编写算法将这两
个单链表归并为一个按元素值递减次序排列的单链表,并要求利用原来两个单链表的结点存放归并后的单链表。

   1:采用头插法

复制代码
node *merge(node *p,node *q)
{
    node *r,*pa,*pb;
    pa=p->next;
    pb=q->next;
    p->next=NULL;//头指针
    while(pa&&pb)
    {
        if(pa->a<pb->a)
        {
            r=pa->next;//记录pa移动的下一个位置
            pa->next=p->next;//将pa的下一个位置指向p的头节点
            p->next=pa;//将pa当前位置插入头节点
            pa=r;//pa指向下一个位置
        }
        else
        {
            r=pb->next;//记录pa移动的下一个位置
            pb->next=p->next;//将pb的下一个位置指向p的头节点
            p->next=pb;//将pb当前位置插入头节点
            pb=r;//pb指向下一个位置
        }

    }
    if(pa)pb=pa;//剩余的放在pb
    while(pb)
    {
        r=pb->next;
        pb->next=p->next;
        p->next=pb;
        pb=r;
    }
    return p;
}
复制代码

   2:先放两数组,合并数组后排序放入表中

复制代码
node *merge(node *m,node *n)
{
    int m1=0,m2=0,n1=0,n2=0,c1=0,j=0;
    int ar[n],br[m],cr[c];
    node *p=m->next;node *q=n->next;
    node *pp=p,*qq=q;
    while(p!=NULL)
    {
        ar[n1++]=p->a;
        p=p->next;
    }
    while(q!=NULL)
    {
        br[m1++]=q->a;
        q=q->next;
    }
    m2=m1-1;
    n2=n1-1;
    while(c1<m1+n1)
    {
        if(m2>=0&&n2>=0)
        {
          if(ar[n2]<br[m2])
            {
                cr[c1]=br[m2];
                m2--;
                c1++;
            }
            else
            {
                cr[c1]=ar[n2];
                n2--;
                c1++;
            }
        }
        else if(m2<0&&n2>=0)//br走完
        {
            cr[c1]=br[n2];
            n2--;
            c1++;

        }else if(n2<0&&m2>=0)
        {
            cr[c1]=br[m2];
            m2--;
            c1++;
        }

    }
    while(pp!=NULL)//pp开始赋值
    {
        pp->a=cr[j++];
        pp=pp->next;
    }
    pp=qq;//pp后面直接连上qq
    while(qq!=NULL)//qq开始赋值
    {
        qq->a=cr[j++];
        qq=qq->next;
    }
    return m;//返回头结点

}
复制代码

14:设A和B是两个单链表(带头结点),其中元素递增有序。设计一个算法从A和B中的公共元素产生单链表C,要求不破坏A ,B的结点。
//从第一个元素依次比较A,B两表元素,不等较小指针往后移,相等创建新节点使用尾插放到新链表,将两表元指针后移直至其中一表为空

复制代码
node *same(node *p,node *q)
{
    node *c=(node *)malloc(sizeof(node));//新链表头结点
    c->next=NULL;
    node *cc=c;
    p=p->next;q=q->next;
    while(p&&q)
    {
        if(p->a==q->a)
        {
            node *tem=(node *)malloc(sizeof(node));
            tem->a=p->a;
            tem->next=NULL;

            cc->next=tem;
            cc=tem;

            p=p->next;
            q=q->next;
        }
        else if(p->a<q->a)p=p->next;
        else q=q->next;
    }
    return c

}
复制代码

15:已知两个链表A和B 分别表示两个集合,递增排列。编制函数,求A与B的交集,并存放于A链表中。

采用归并的思想,设置1工作指针pa,pa对链表进行归并扫描,只要同时出现在两者的元素才连接到结果表中且仅保留一个
,其他节点全部释放,当一个链表遍历完毕后,释放另一个表中剩下的全部节点

复制代码
node *union(node &la,node &lb)
{
    node *pa=la->next;
    node *pb=lb->next;
    node *pc=la;
    node *u;
    while(pa&&pb)
    {
        if(pa->a==pb->a)
        {
            pc->next=pa;//pc表增加节点
            pc=pa;//pc移动到pc表尾结点
            pa=pa->next;//pa指向下一个pa元素
            u=pb;//释放pb节点
            pb=pb->next;//pb指向pb下一个元素
            free(u);
        }
        else if(pa->a<pb->a)//pa值小于pb值 释放pa pa指向下一个pa
        {
            u=pa;
            pa=pa->next;
            free(u);
        }
        else//pa值大于pb值 释放pb pb指向下一个pa 直到pa=pb 或者小于pb
        {
            u=pb;
            pb=pb->next;
            free(u);
        }
    }
    while(pa)//如果pb已经释放完毕,pa还在,已经没有要比较的必要,释放pa下边的所有元素
    {
        u=pa;
        pa=pa->next;
        free(u);
    }
    while(pb)
    {
        u=pb;
        pb=pb->next;
        free(u);
    }
    pc->next=NULL;
    free(lb);
    return la;
}
复制代码

16:两个整数序列a1,a2,a3....am和b1,b2,b3,,,bn已经存入两个单链表中,设计一个算法,判断序列B是否是序列A的的连续子序列。m>n

复制代码
void sonOfa(node *A,node *B)
{
    node *p,*pp,*q,*qq;
    p=A->next;
    while(p)
    {
        q=B->next;
        if(p->a!=q->a)
        {
            p=p->next;
            continue;
        }
        pp=p;
        while(pp!=NULL&&pp->a==q->a)
        {
            pp=pp->next;
            q=q->next;
        }
        if(q==NULL)return q;
        else p=p->next;

    }
}
复制代码

 17:设计空间复杂度为o(1)  带头结点a1 a2 a3 a4....an重新排列各节点的a1 an a2 an-1 a3 an-2 .........

定义数据结构

typedef struct nodes
{
    int data;
    struct node *next;
}NODE;

正文

 1:书上方法

     1找到L中间节点,设置两个指针,p走一步 q走两步 当q到链尾 p到中间节点
     2将L后半段节点原地逆置
     3从单链表前后两端中依次各取一个节点

1 2 3 4     5    6 7 8 9

p=5 null

q=6

r=null

复制代码
void changeList(NODE *h)
{
    NODE *p,*q,*r,*s;
    p=q=h;
    while(q->next!=NULL)//寻找中间节点
    {
        p=p->next;//p走一步
        q=q->next;
        if(q->next!=NULL)q=q->next;//q走两步
    }
    q=p->next;//p中间节点,q后半段首节点
    p->next=NULL;
    while(q!=NULL)//后半段逆转
    {
        r=q->next;//存放当前值r:7  8  9 null
        q->next=p->next;//q:6 null     7 6 null    8 7 6 null     9 8 7 6 null
        p->next=q;      //p:5 6 null   5 7 6 null  5 8 7 6 null   5 9 8 7 6 null
        q=r; //q:7 8 9 null
    }
    s=h->next;//s:1 2 3 4
    q=p->next;//q:[9] 8 7 6 null
    p->next=NULL;//p:5 NULL
    while(q!=NULL)//将后半段插入到相应位置
    {
        r=q->next;      //r: 8 7 6 null     7 6 null       6 null             null
        q->next=s->next;//q: 9 2 3 4        8 3 4          7 4                6
        s->next=q;      //s: 1 9 2 3 4      1 9 2 8 3 4    1 9 2 8 3 7 4      1 9 2 8 3 7 4 6
        s=q->next;      //s: 2 3 4          3 4            4                  null
        q=r;            //q: 8 7 6 null     7 6 null       6 null             null
    }

}
复制代码

2:我的方法

复制代码
概述
例子1:
1 2 3 4 5 6 7 8 9 1 9 2 8 3 7 4 6 5 len=9 len=len-2 len>=0
第一趟:
.7 1 3 4 5 6 7 8 9 2 temp=cur->next=2 cur=1 p=cur p->next=temp->next p=temp ....p=null p->next=temp cur temp p pp p->next=pp->next pp=pp->next p pp p->next=pp->next pp=pp->next p pp 1 4 5 6 7 8 9 2 3 temp=cur->next=3 cur=1 p=cur p->next=temp->next p=temp ....p=null p->next=temp 1 5 6 7 8 9 2 3 4 temp=cur->next=4 cur=1 p=cur p->next=temp->next p=temp ....p=null p->next=temp 1 6 7 8 9 2 3 4 5 temp=cur->next=5 cur=1 p=cur p->next=temp->next p=temp ....p=null p->next=temp 1 7 8 9 2 3 4 5 6 1 8 9 2 3 4 5 6 7 1 9 2 3 4 5 6 7 8 temp=cur->next=8 cur=1 p=cur p->next=temp->next p=temp ....p=null p->next=temp
第二趟: .
5 1 9 2 4 5 6 7 8 3 temp=cur->next=3 cur=cur->next->next=2 p=cur p->next=temp->next p=temp ....p=null p->next=temp 1 9 2 5 6 7 8 3 4 1 9 2 6 7 8 3 4 5 1 9 2 7 8 3 4 5 6 1 9 2 8 3 4 5 6 7temp=cur->next=7 cur=cur->next->next=2 p=cur p->next=temp->next p=temp ....p=null p->next=temp
第三趟: .
3 1 9 2 8 3 5 6 7 4 1 9 2 8 3 6 7 4 5 1 9 2 8 3 7 4 5 6 第四趟:
.
1 1 9 2 8 3 7 4 6 5 例子2: 1 2 3 4 5 6 1 6 2 5 3 4 第一趟:
.
4 1 3 4 5 6 2 1 4 5 6 2 3 1 5 6 2 3 4 1 6 2 3 4 5 第二趟:
.
2 1 6 2 4 5 3 1 6 2 5 3 4 . 0
复制代码
复制代码
void vers(NODE &L)
{
    int len=0,j;
    NODE *p=L->next,*q,*qq,*cur,*temp,*pp;
    cur=p;
    while(p!=NULL)
    {
        L=L->next;
        len++;
    }
    len=len-2;
    while(len>1)
    {
        for(j=0;j<len;j++)//将最后一个放到首个数的后边 重新形成链表
        {
            //cur=q;
            qq=cur;
            temp=cur->next;
            pp=temp;
            while(pp!=NULL)
            {

                qq->next=pp->next;
                pp=pp->next;
                qq=qq->next;
            }
            qq=temp;
            qq->next=NULL;

        }
        cur=cur->next->next;
        len=len-2;
    }

}
复制代码

18:设计一个算法判断链表是否有环,有的话找到入口点并返回,否则返回null(注意此题!

两个节点慢点每次走一步,快点每次走两步,快点先进入环,慢点后进入,快慢点相遇表明存在----------2(a+x)=a-n*r+x ->a=n*r-x

复制代码
概述
为什么 两个指针相遇的地方就是环入口点?
  先从"判断链表是否有环"的那种情况说起.
  假设从链表头到环入口点的距离是x, 在环里两个指针相遇的那点与环入口点的距离是w,
  fast指针在环里走了n圈才与slow相遇,环的长度是L,那么,
  slow指针在相遇时走过的距离是 x + w
  fast指针走过的距离是 x + w + n*L
  因为slow每次向前走一步,而fast每次向前走两步,有如下等式:
  2 * (x + w) = x + w + n*L
  化简得到: x + w = n*L
  也就是 x = n*L - w  [等式1]
  假设相遇的时候,fast在环内只走了一圈,n=1,代入[等式1],得到 x = L - w
  现在,slow从链表头开始走,fast继续从相遇点开始走,两个指针都只走一步,
  那么,slow走了x,而fast走了(L - w),必定相遇,而且刚好在环入口点.
  假设相遇的时候,fast在环内走了超过一圈,那么[等式1]可以写为:
  x = (n-1)*L + (L- w)
  那么,slow走了x,而fast走了(n-1)圈后,再走(L - w),必定相遇,而且刚好在环入口点.
复制代码
复制代码
typedef struct Lnode
{
    int data;
    struct Lnode *next;
}Lnode *Lnode;
Lnode *circle(Lnode *head)
{
    Lnode *fast=head,*slow=head;
    while(slow!=NULL&&fast->next!=NULL)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)break;
    }
    if(slow==NULL||fast->next==NULL)
    {
        return NULL;
    }
    Lnode *p1=head,*p2=slow;
    while(p1!=p2)
    {
        p1=p1->next;
        p2=p2->next;
    }
    return p1;
}
复制代码

19:对于带头结点的链表中绝对值相等的节点保留第一次出现的节点删除其余节点

1:我的

复制代码
typedef struct jdz
{
    int data;
    struct jdz *link;
}jdz,*jdz;
void deljdz(jdz &Llist)
{
    jdz *p,*q,*qq;//分别指向移动位数,往前走判断
    p=Llist->link;//指向第一个结点
    while(p->link!=NULL)
    {
        q=p;//q指向p开始的节点
        while(q!=NULL)
        {
            qq=q->link;//qq指向q的下一个节点,第一次是p的下一个节点,
            if(abs(p->data)==abs(qq->data))//绝对值相等删除 q的位置不变
            {
                q->link=qq->link;
                free(qq);
            }
            else//绝对值不相等 q向前走
            {
                q=q->link;
            }
        }
        p=p->link;//p往前走

    }
}
复制代码

2:书上,用空间换时间 使用数组存储数字,在数组中删除绝对值删除的数,之后存到链表

复制代码
void func(jdz *h,int n)
{
    jdz *p=h,*r;
    int *q,m;
    q=(int *)malloc(sizeof(int)*(n+1));
    for(int i=0;i<n+1;i++)
    {
        *(q+i)=0;
    }
    while(p->link!=NULL)
    {
        m=p->link->data>0?p->link->data:-p->link->data;
        if(*(q+m)==0)//第一次出现
        {
            *(q+m)=1;
            p=p->link;
        }
        else
        {
            r=p->link;
            p->link=r->link;
            free(r);
        }
    }
    free(q);
}
复制代码

20:找后缀相同的起始位置

书上解法:较长的那串字符串从头结点一直走,直到长短字符串长度相等,在向后移动一一比较,直到指向同一位置时停止,即为后缀开始开始(前边第八题)

我的解法:

复制代码
typedef struct strList
{
    char data;
    struct strList *link;
}strList,*pstrList;
strList *getStart(strList &str1,strList &str2)
{
    strList *p,*pp,*q,*qq,*qqq;
    p=str1;q=str2;//p长的,q短的
    while(p!=NULL)
    {
        
        qq=q;
        while(qq!=NULL&&p->data!=qq->data)
        {
            qq=qq->link;
        }
        if(q==NULL)//没有相同值
        {
            p=p->link;
            continue;
        }
        pp=p;
        qqq=qq;
        while(pp->data==qqq->data)
        {
            pp=pp->link;qqq=qqq->link;
        }
        if(pp==NULL&&qqq==NULL)//走到了头是公共的返回
        {
            return qq;
        }
        else p=p->link;//继续往下走

    }
    return 0;
}
复制代码

21:找倒数第k个数

书上解法:设置两个节点指针,一个指针移动到k位置之后,另一个节点开始移动,一个节点移动到末尾,另一个节点走了n-k步数,就是倒数第k个

我的解法:计算链表长度len,从头第len-k个即为倒数第k个

复制代码
typedef struct linkList
{
    int data;
    struct linkList *link;
}linkList,*plinkList;
int seekk(linkList &list,int k)
{
    int len=0,len1;
    linkList *p;
    p=list;
    while(p!=NULL)
    {
        p=p->link;
        len++:
    }
    len1=len-k;//第几个数
    if(k<0||k>len)
    {
        return 0;
    }
    else
    {
        while(len!=0)
        {
            list=list->link;
            len--;
        }
        printf("%d",list->data);
        return 1;
    }


}
复制代码

 22:从键盘输入一行字符,调用一个函数建立反向序列的单链表(不带头结点),然后输出整个单链表

    (1)书上的:ins(head,p)建立反序列的不带头节点的单链表,将节点*p插入到以head为首节点指针的单链表的最前端,

           这样需要修改head指针,返回修改的值给对应的实参,因为head本身是指针类型,有需要采用传地址方式,所以采用NODE**head形参

 

复制代码
typedef struct node
{
    int data;
    struct node *next;
}NODE;
void main()
{
    char ch;
    NODE *p,*head;
    head=NULL;
    while((ch=getchar())!='\n')
    {
        p=(NODE *)malloc(sizeof(NODE));
        p->data=ch;
        ins(&head,p);//由于hrad是一级指针,所以实参为&p
    }
    p=head;
    while(p!=NULL)
    {
        printf("%c",p->data);
        p=p->next;
    }
    printf("\n");
}
void ins(NODE **hp,NODE *q)//  *hp形参是一个二级指针
{
    if(hp==NULL){q->next=NULL;*hp=q;}//第一个q作为头结点hp
    else{q->next=*hp;*hp=q}//新节点指向hp,hp移到新节点处
}
复制代码

    (2)我的:输入字符放入数组中,函数从数组倒序建立节点,放入列表,调用函数,返回头指针,输出

 

复制代码

typedef struct node
{
    char ch;
    struct node *next;
}NODE;
NODE *ope(char a[],int i)
{
    NODE *w=NULL;
    NODE *q,*s;
    int j;
    printf("1 i=%d\n",i);
    for(j=i-1;j>=0;j--)
    {
        printf("2 j=%d\n",j);
        q=(NODE *)malloc(sizeof(NODE));
        printf("test %c\n",a[j]);
        q->ch=a[j];
        //strcpy(q->ch[0],a[j]);
        printf("3 q=%c\n",q->ch);
        if(w==NULL)w=s=q;
        else{s->next=q;s=q;}
    }
    s->next=NULL;
    return w;
}
void main()
{
    NODE *p;
    char chs[50];
    int i=0;
    while(i<50&&(chs[i++]=getchar())!='\n');
    chs[(i==50)?i:i-1]='\0';
    printf("%s\n",chs);
    p=ope(chs,i-1);
    while(p!=NULL)
    {
        printf("%c",p->ch);
        p=p->next;
    }

}
复制代码

 23:每行文字长不超过80字符,每个单词由空格,\t,\n分割,单词长度不超过20字符,要求从键盘输入一段英文文字,输入stop后,结束输入。统计这段文字中每个单词出现次数

aaa bbb cc sss 123 4567 cc
456 4567 aaa cc sss 123 123
123 stop
aaa(2) bbb(1) cc(3) sss(2)

 

复制代码
struct table
{
    char dat[20];
    int num;
    struct table *next;
};
int main()
{
    char str[20];
    //遇到‘’  \t,\n存入数组,用scanf来获取输入的单词
    struct table *p,*t,*q,*m;
    p=(struct table *)malloc(sizeof(struct table));
    char sss[]="统计结果:";
    strcpy(p->dat,&sss);
    p->next=NULL;
    t=p;
    int in;
    printf("请输入:\n");
    while(1)
    {
        scanf("%s",str);
        in=0;
        m=p->next;//指向链表开头头结点
        if(strcmp(str,"stop")==0)//输入stop跳出循环
        {
            break;
        }
        while(m!=NULL)//把str与链表值逐个比较
        {
            if(strcmp(m->dat,str)==0)//找到了
            {
                in=1;
                m->num=m->num+1;//个数+1;
            }
            m=m->next;
        }
        if(in==0)//链表中不存在该字符
        {
            q=(struct table *)malloc(sizeof(struct table));
            strcpy(q->dat,str);
            q->num=1;
            t->next=q;
            t=q;
            t->next=NULL;
        }
    }
    printf("%s",p->dat);
    p=p->next;
    while(p!=NULL)
    {
        printf("%s(%d) ",p->dat,p->num);
        p=p->next;
    }
}
复制代码

24:若干个班,每个班人数不等,每个学生含姓名,分数数据,编写程序输出各班学生姓名和分数后,统计各班平均分并输出各班学生分数与平均分

复制代码
struct stu
{
    char name[10];
    int score;
    struct stu *next;
};
struct sclass
{
    int id;
    char name[10];
    int totalScore;
    struct stu *next;
};
struct sclass *allclass[100];//存放班级头结点
//输入一个班的人数和学生信息 输入#代表一个班级结束
//1:输入班级编号作为头结点指向下一个输入的学生,输入#代表该班级循环结束
//2:判断是否继续输入班级,继续输入*,计算平均分数输入$
//3:将班级节点放入班级结构体数组
//计算平均分时输出总成绩和每个人成绩
void creatClass(int no)
{
    struct sclass *p;//头结点
    struct stu *pp,*t,*q;//
    char nn[10];int sc;//学生信息

    char cn[10];//班级信息
    p=(struct sclass *)malloc(sizeof(struct sclass));//头结点
    printf("请输入%d班级名称: ",no);
    gets(cn);
    p->id=no;
    strcpy(p->name,cn);
    allclass[no]=p;

    printf("请输入学生信息,输入#结束:\n");
    pp=(struct stu *)malloc(sizeof(struct stu));//新头结点
    p->next=pp;//班级指向第一个学生
    t=pp;//t始终指向尾结点

    while(1)
    {
        printf("输入学生姓名:");
        gets(nn);
        if(strcmp(nn,"#")==0)
        {
           break;
        }
        printf("输入学生分数:");
        scanf("%d",&sc);
        getchar();
        q=(struct stu *)malloc(sizeof(struct stu));//新其余结点
        strcpy(q->name,nn);
        q->score=sc;
        t->next=q;
        t=q;
    }
    t->next=NULL;

};
void getAve(int num)
{
    int i=0;
    int sum,k;
    for(i=0;i<num;i++){
        sum=0;k=0;
        printf("班级%d:%s\n",i,allclass[i]->name);
        struct stu *tem,*f;
        tem=allclass[i]->next;
        tem=tem->next;
        while(tem!=NULL)
        {
            printf("学生%s:分数%d\n",tem->name,tem->score);
            sum+=tem->score;
            k++;
            //f=tem;
            tem=tem->next;
            //free(f);
        }
        printf("平均分%d\n",sum/k);
    }
}

int main()
{
    int sel,classNo=0;
    while(1)
    {
        printf("1:添加班级;2:计算班级平均分;3:退出\n");
        scanf("%d",&sel);
        getchar();
//gets()用于读入整行字符串,以回车结尾。因为你在scanf("%d",&n);时已经读入一个回车,
//所以第一个a为空字符。(输入的数字赋值给n,然后回车给a了)。解决办法是scanf("%d",&n);后加一句getchar();
        if(sel==1)
        {
            creatClass(classNo);
            classNo++;
        }
        else if(sel==2)
        {
            getAve(classNo);
        }
        else break;
    }


}
复制代码

 

posted on   Y-flower  阅读(557)  评论(0编辑  收藏  举报

编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示