• 链表


    链表的建立:

    两种思路——(1)顺序建立:在后面添加结点,定义一个head指针,head->next指向的是第一个结点的地址,

            p=head;   

            q=(...) malloc ( sizeif (...) );

            …… 

            p->next=q;

            p=q;

            利用for循环不断向后建立若干个结点

            最后把p->next=NULL;

          (2)逆序建立:即在前面添加结点,过程:建立一个结点,next指向NULL,再定义一个结点,next指向前一个定义的结点,以此类推,最后得到的是第一个结点的地址。

    结点的删除:p指向前一个结点,q指向后一个。p->next=q->next;  这样q指向的结点就被删除了。

    结点的后移:p=p->next;   结点无法前移。

    结点的插入:pp指向新结点,p指向前一个结点,q指向后一个。 p->next=pp ; pp->next=q;   这样pp指向的结点就被插入在p和q指向的结点中间。

    下面是有两个例子

    例一:顺序建立链表

    #include
    #include
    struct StuNode
    {
    	int num;
    	char name[20];
    	char sex[5];
    	int age;
    	struct StuNode *next;
    }*head,*p,*q;
    int main()
    {
    	int i,n,ag,flag;
    	printf("input n=?");                                           //录入信息的学生个数
    	scanf("%d",&n);
    	head=(struct StuNode *)malloc(sizeof(struct StuNode));         //记下表头地址         注意 *
    	head->next=NULL;                                               //??? 答:相当于给head->next 初始化了,之后还可以指向别的地方 
    	p=head;                                                        //p指向了head——空头结点地址 
    	printf("\ninput student's data\n");
    	for(i=0;i<n;i++)
    	{
    		q=(struct StuNode *)malloc(sizeof(struct StuNode));
    		scanf("%d%*c",&q->num);
    		gets(q->name);
    		gets(q->sex);
    		scanf("%d",&q->age); 
    		p->next=q;                                                //p->next指向了q——下一个结点的地址, 
    		p=q;                                                      //顺序建立结点 
    	}
    //	free(q);
    	p->next=NULL;                                                 
    	p=head->next;                                                        //p回到第一个结点(head的作用是引出第一结点的地址,即head->next) 
    	printf("\ndisplay linklist\n");
    	for(i=0;i<n;i++)                                                //打印链表内容 
    	{
    		printf("%d\t",p->num);
    		printf("%s\t",p->name);
    		printf("%s\t",p->sex);
    		printf("%d\n",p->age);
    		p=p->next;
    	}
    	printf("\ninput age to be deleted:");
    	while(scanf("%d",&ag)&&ag!=0)                                   //scanf,正确读取则返回数据个数,出错返回0 
    	{
    		flag=0;
    		p=head;                                                      //p在前,q在后 
    		q=p->next;                                                   //p->next指向第一结点地址 ,即q指向 
    		while(q)                                                     //循环直到q=NULL,即指向最后一个结点 
    		{
    			if(ag==q->age)
    			{
    				flag=1;
    				if(q->next!=NULL)
    					p->next=q->next;                                  //删除结点 
    				else
    					p->next=NULL;                                     //q->next=NULL说明这是最后一个结点 
    				printf("delete success!\n");
    				break;
    			}
    			else{
    				p=p->next;
    				q=q->next;
    			}                                   //结点后移
    
    		}
    		if(flag==0)
    			printf("can't find!\n");
    		else{                                    //输出删除结点后的单链表 
    			p=head->next;
    			printf("\ndisplay linklist after one node was deleted\n");
    			for(i=0;i<n;i++){
    				printf("%d\t",p->num);
    				printf("%s\t",p->name);
    				printf("%s\t",p->sex);
    				printf("%d\n",p->age);
    				p=p->next;
    			}
    		}
    	}
    	free(p);
    	free(q);
    	free(head); 
    	return 0;
    }
    

    例二,逆序建立链表

    #include
    #include
    #include
    struct Node
    {
    	char nu[5],name[10],sex[5],age[5];
    	struct Node *next;
    };
    struct Node *input();
    void del(struct Node *f);
    void output(struct Node *f);
    
    int main()
    {
    	struct Node *f=NULL;
    	f=input();          //信息录入,在前加,返回的是第一节点的地址
    	printf("======删除前======\n");
    	output(f);
    	del(f);            //信息删除,
    	printf("======删除后======\n");
    	output(f);
    	return 0;
    }
    
    struct Node *input()
    {
    	int i;
    	struct Node *f=NULL,*s=NULL;
    	for(i=0;i<5;i++){
    		s=(struct Node*)malloc(sizeof(struct Node));
    		printf("第%d位学生:",i);
    //		scanf("%s/%s/%s/%s",s->nu,s->name,s->sex,s->age);
    		gets(s->nu);
    		gets(s->name);
    		gets(s->sex);
    		gets(s->age);         
    		s->next=f;
    		f=s;
    	}
    //	free(s);
    	return f;                        //s为最后一个节点的首地址
    }
    
    void del(struct Node *f)
    {
    	char a[5];               //年龄值
    	struct Node *p=f,*s=f;
    	gets(a);
    	
    	while(p!=NULL){
    		if(strcmp(a,f->age)==0){                   //如果第一个就是
    			f=s->next;
    			p=f;
    			s=f;
    		}
    		else if(strcmp(a,p->age)==0){
    			s->next=p->next;
    		}
    		s=p;
    		p=p->next;
    	}
    }
    
    void output(struct Node *f)
    {
    	struct Node *r=f;
    	while(r!=NULL){
    		printf("number:%s\t",r->nu);
    		printf("name:%s\t",r->name);
    		printf("sex:%s\t",r->sex);
    		printf("age:%s\n",r->age);
    		r=r->next;
    	}
    }
    	
    两个代码,前一个是按书上的敲的,后一个是自己敲得,开始的时候对书上的哪些内容看不太懂,经过反复推敲,总算有了些眉目,全都写在注释里了,下面再来总结一下吧:
    (1)顺序建立链表必须有一个“head”来指引第一个结点;
    (2)指针指向NULL,相当于初始化,也是避免野指针造成的风险;
    (3)哪怕是数字,也可以用字符串表示,用字符串格式输出,如例二的age。

    感谢阅读!
  • 相关阅读:
    浅谈.NET下的多线程和并行计算系列文章索引
    浅谈.NET下的多线程和并行计算(六)线程池基础下
    浅谈.NET下的多线程和并行计算(八)Winform中多线程编程基础上
    项目优化经验——垃圾回收导致的性能问题
    浅谈.NET下的多线程和并行计算(五)线程池基础上
    站点静态资源优化合并解决方案
    浅谈.NET下的多线程和并行计算(二)线程基本知识
    浅谈.NET下的多线程和并行计算(十二)CLR via C#第三版阅读笔记(1)
    原谅我的说谎
    索爱手机GPRS的OTA设置[转]
  • 原文地址:https://www.cnblogs.com/liulangbxc/p/10987666.html
Copyright © 2020-2023  润新知