C语言练习-day24

题目:假设该链表只给出了头指针L,在不改变链表的前提下,请设计一个尽可能高效的算法,查找链表中倒数第k个位置上的结点(k为正整数)。若查找成功,算法输出该结点data域的值,并返回1;不则只返回0。

输入:带头结点的链表个元素的值,类型为int,以9999结束。

输出:查找倒数的k个结点,输出该元素值。

优化目标:无。

算法思想:定义两个指针p和q,初始时均指向头结点的下一个结点(链表的第一个结点),p指针沿链表移动;当p指针移动到第k个结点时,q指针开始和p指针同步移动,当p指针移动到最后一个结点时,q指针所指示结点为倒数第k个结点。

#include<stdio.h>
#include<stdlib.h>

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LinkList;


int Search_k(LinkList L,int k){
    LNode *p,*q;
    p = L->next;
    q = L->next;
    int count = 0;
    while(p!=NULL){
        if(count<k){
            count++;
        }
        else{
            q = q->next;
        }
        p = p->next;
    }
    if(count<k){
        return -1;
    }
    else{
        return q->data;
    }
}

//创建链表
void creatList(LinkList &L){
    LNode *s,*r;
    int x;
    printf("请输入链表元素值(以9999结束):");
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    r = L;
    scanf("%d",&x);
    while(x!=9999){
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        s->next = NULL;
        r = s;
        scanf("%d",&x);
    }
}

//输出链表
void PrintList(LinkList L){
    LNode *p = L->next;
    printf("链表元素有:");
    while(p!=NULL){
        printf("%d   ",p->data);
        p = p->next;
    }
    printf("\n");
}



int main() {
	LinkList L;
	creatList(L);
	PrintList(L);
	printf("请输入想要查询倒数的位置:");
	int k;
	scanf("%d",&k);
	int kk = Search_k(L,k);
	printf("查找的结点是:%d",kk);
	return 0;
}

题目:用单链表保存m个整数,结点的结构为[data][ next],且ldatal<=n(n为正整数)。现要求设计一个时间复杂度尽可能高效的算法,对于链表中data的绝对值相等的结点,仅保留第一次出现的结点而删除其余结点。

输入:带头结点的链表个元素的值,类型为int,以9999结束。

输出:删除绝对值相等的结点之后,输出单链表。

优化目标:无。

算法思想:用空间换时间。使用辅助数组记录链表中已经出现的数值,从而只需对链表进行一趟扫描。

#include<stdio.h>
#include<stdlib.h>

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LinkList;

void del_absrepeat(LinkList L){
    LNode *p = L,*s;
    int *q,m,n = 0;
    s = L;
    while(s->next!=NULL){
		n++;
		s = s->next;
	}
    q = (int *)malloc(sizeof(int)*(n+1));
    for(int i = 0;i<n+1;i++){
        *(q+i) = 0;
    }
    while(p->next!=NULL){
        if(p->next->data>0){
            m = p->next->data;
        }
        else{
            m = -(p->next->data);
        }
        if(*(q+m) == 0){
            *(q+m) = 1;
            p = p->next;
        }
        else{
            s = p->next;
            p->next = s->next;
            free(s);
        }
    }
    free(q);
}


//创建链表
void creatList(LinkList &L){
    LNode *s,*r;
    int x;
    printf("请输入链表元素值(以9999结束):");
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    r = L;
    scanf("%d",&x);
    while(x!=9999){
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        s->next = NULL;
        r = s;
        scanf("%d",&x);
    }
}

//输出链表
void PrintList(LinkList L){
    LNode *p = L->next;
    printf("链表元素有:");
    while(p!=NULL){
        printf("%d   ",p->data);
        p = p->next;
    }
    printf("\n");
}



int main() {
	LinkList L;
	creatList(L);
	PrintList(L);
	del_absrepeat(L);
	PrintList(L);
	return 0;
}

题目:暗点设计一个算法完成以下功能:判断一个链表是否有环,如果有,找出环的入口并返回,否则返回NULL。

输入:创建带头结点的链表(带环)个元素的值,类型为int,以9999结束。

输出:找到环的入口点,输出入口点的值。

优化目标:无。

算法思想:设置快慢两个指针分别为fast和slow,slow每走一步,fast走两步,所以如果有环,那么fast一定会先进入环,而slow后进入环。当两个指针都进入环后,经过若干次操作后两个指针一定能在环上相遇。这样就可以判断一个链表是否有环。设头结点到环入口的距离为a,环的入口点沿环的方向到相遇点的距离为x,环长尾r入队,相遇时fast绕过了n圈,所以2(a+x)=a+n*r+x,即a=n*r-x,所以从头结点到环入口点的距离等于环长减去环的入口点到相遇点的距离,所以设置两个指针,一个指向L,一个指向相遇点,两个指针同步移动(均一次移动一步),相遇点就是环的入口点。

#include<stdio.h>
#include<stdlib.h>

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LinkList;

LNode* FindLoopStart(LinkList L){
    LNode *fast = L->next,*slow = L->next;
    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 = L->next,*p2 = slow;
    while(p1!=p2){
        p1 = p1->next;
        p2 = p2->next;
    }
    return p1;
}


//创建链表
void creatList(LinkList &L){
    LNode *s,*r,*p;
    int x;
    printf("请输入链表元素值(以9999结束):");
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    r = L;
    scanf("%d",&x);
    
    
    s = (LNode *)malloc(sizeof(LNode));
    s->data = 1;
    r->next = s;
    s->next = NULL;
    r = s;
	s = (LNode *)malloc(sizeof(LNode));
    s->data = 2;
    r->next = s;
    s->next = NULL;
    r = s;
	s = (LNode *)malloc(sizeof(LNode));
    s->data = 3;
    r->next = s;
    s->next = NULL;
    r = s;
    
    p = s;
    
    while(x!=9999){
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        s->next = NULL;
        r = s;
        scanf("%d",&x);
    }
    r->next = p;
}

//输出链表
void PrintList(LinkList L){
    LNode *p = L->next;
    printf("链表元素有:");
    while(p!=NULL){
        printf("%d   ",p->data);
        p = p->next;
    }
    printf("\n");
}



int main() {
	LinkList L;
	creatList(L);
	LNode *p = FindLoopStart(L);
	printf("入口结点元素是:%d",p->data);
	
	return 0;
}

题目:设线性表L = (a1a2,a3,...,a(n-2),a(n-1),an)采用带头结点的单链表保存,请设计一个空间复杂度为O(1),且时间上尽可能高效的算法,重新排列L中的各结点,得到线性表L‘ = (a1,a(n),a2,a(n-1),a3,a(n-2))。

输入:带头结点的链表个元素的值,类型为int,以9999结束。

输出:按要求排序好单链表后,输出单链表。

优化目标:无。

算法思想:首先取出表的后半段,利用p和q指针,p移动一步,q移动两步,当q到达表尾时,p正好在链表的中间结点,然后将L的后半段结点原地逆置,从单链表前后两段各取一个结点,按要求重排。

#include<stdio.h>
#include<stdlib.h>

typedef struct LNode{
    int data;
    struct LNode *next;
}LNode,*LinkList;


void change_List(LinkList &L){
    LNode *p,*q,*r,*s;
    p = q = L;
    while(q->next!=NULL){
        p = p->next;
        q = q->next;
        if(q->next!=NULL){
            q = q->next;
        }
    }
    q = p->next;
    p->next = NULL;
    while(q!=NULL){
        r = q->next;
        q->next = p->next;
        p->next = q;
        q = r;
    }
    s = L->next; 
    q = p->next;
    p->next = NULL;
    while(q!=NULL){
        r = q->next;
        q->next = s->next;
        s->next = q;
        s = q->next;
        q = r;
    }
}

//创建链表
void creatList(LinkList &L){
    LNode *s,*r;
    int x;
    printf("请输入链表元素值(以9999结束):");
    L = (LinkList)malloc(sizeof(LNode));
    L->next = NULL;
    r = L;
    scanf("%d",&x);
    while(x!=9999){
        s = (LNode *)malloc(sizeof(LNode));
        s->data = x;
        r->next = s;
        s->next = NULL;
        r = s;
        scanf("%d",&x);
    }
}

//输出链表
void PrintList(LinkList L){
    LNode *p = L->next;
    printf("链表元素有:");
    while(p!=NULL){
        printf("%d   ",p->data);
        p = p->next;
    }
    printf("\n");
}



int main() {
	LinkList L;
	creatList(L);
	PrintList(L);
	change_List(L);
	PrintList(L);
	
	return 0;
}

今日总结:做了几道单链表的题,还要好好复习之前的内容,今天题总体来说不是很难,后面还要加油多练。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
(1)用带表头的链表存放输入的数据,每读入一个数,按升序顺序插入到链表中,链表中允许两个结点有相同值。链表的头结点存放链表后面的结点个数,初始化时就生成头结点(初值为0)。链表翻转是把数据逆序(变成降序),注意,头结点不动。翻转后要再翻转一次,恢复升序后才能插入新元素,否则会出错。 (2)先定义堆栈的几个基本操作,再设计一主函数利用堆的操作完成以下功能:假设一个算术表达式中可以包含三种括号:()[]{},且这三种括号可以按任意次序嵌套使用(如:...[...{...}...[...]...]...(...))。编写判别给定表达式中所含括号是否正确配对出现的算法,已知表达式已存入数据元素为字符的单链表中。 (3)先定义队列的几个基本操作,再设计一主函数利用队列的操作完成以下功能:键盘输入的字符可以临时存入键盘的缓冲区中。为了充分利用缓冲区的空间,往往将缓冲区设计成链式循环队列的结构,并为循环队列结构的缓冲区设置一个队首指针和一个队尾指针。每输入一个字符到缓冲区中,就将尾指针后移,链入缓冲区的循环队列之中;每输出一个字符号,就将队头指针前移,将它从缓冲队列中删除。假设有两个进程同时存在于一个应用程序中,第一个进程连续在屏幕上显示字符“X”,第二个进程不断检查键盘上是否有输入,若有则读入用户键入的字符,将其保存到键盘缓冲区中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值