链表

链表的建立:

两种思路——(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。

感谢阅读!
posted @ 2019-06-07 09:53  叶际参差  阅读(143)  评论(0编辑  收藏  举报