• C语言语法教程-链表


    链表是一群结构体(称为结点)通过指针连起来。这种结构体类型,比较特殊,叫自引用结构体类型。它有一个指针指向和和结构体一样的类型,其余是数据成员。
    头指针指向第一结点,尾指针一定要用空表示,这叫有头有尾。一般在表头加头结点,之后才是正式含数据的结点。
    这些结点通过头指针访问,所以若头指针值为空,那么链表就为空。所以头指针是最重要的,一般一定会给函数传递头指针。

    //-------------------------------------
    //--- linked list.1
    //--- 使用链表管理学生信息
    //-------------------------------------
    #include <stdio.h>
    #include <stdlib.h>
    
    struct student
    {
    	long no;
    	char name[20];
    	char addr[30];
    	struct student *next;
    };
    
    typedef struct student LIST;
    LIST *CreateList();
    void DispList(LIST *h);
    void input(LIST *p);
    LIST *DeleteNode(LIST *h, long no);
    LIST *InsertNode(LIST *h, LIST *s);
    
    int main(int argc, char const *argv[])
    {
    	LIST *head,*p;
    	long no;
    	int choice,confirm;
    	head=CreateList();    //创建链表,返回头指针
    	DispList(head);          //输出链表内信息
    	while(1)
    	{
    		printf("0--Insert
    1--Delete
    2--Quit
    Please select:");
    		scanf("%d",&choice);
    		if(choice==2)
    			break;
    		printf("your just select %d,yes? ",choice);
    		scanf("%d",&confirm);
    		if(confirm){
    			switch(choice)
    			{
    				case 0:
    					printf("OK,now we insert a record!
    ");
    					printf("======Insert=====
    ");
    					p=(LIST *)malloc(sizeof(LIST));
                        if(p == NULL)
                        {
                            printf("Wrong!
    ");
                            exit(0);
                        }
    					input(p);
    					head=InsertNode(head,p);
    					DispList(head);
    					break;
    				case 1:
    					printf("OK,now we delete a record!
    ");
    					printf("======Delete=====
    ");
    					printf("Delete Id:");
    					scanf("%d",&no);
    					head=DeleteNode(head,no);
    					if (head!=NULL)
    						DispList(head);
    					else printf("All records have been deleted!
    ");
    					break;
    			}
    		}
    	}
    	return 0;
    }
    void input(LIST *p)
    {
    	LIST *cur=p;
    	printf("Id:");
    	scanf("%d", &cur->no);	
    	printf("Name:");
    	scanf("%s", &cur->name);
    	printf("Address:");
    	scanf("%s", &cur->addr);
    }
    LIST *CreateList()/*返回头指针,故定义为结构体指针函数。*/
    /*创建链表的函数定义*/
    {
    	LIST *h, *prev, *cur;//这三不是结构体,是工作指针,用来操作的。 
    	int i, n;
    	h=NULL;
    	/*第一个结点过来孤零零的,不知道干啥,所以得弄个头指针。初始化为空。*/
    	printf("Input numbers of records:");
    	scanf("%d",&n);
    
    	for (int i = 0; i < n; i++)//for循环创建链表
    	{
    		cur=(LIST *)malloc(sizeof(LIST));/*LIST型指针,动态生成一个结点空间,返回首地址*/
            if(cur == NULL)
            {
                printf("Wrong!
    ");
                exit(0);
            }
    		cur->next=NULL;/*将cur的next置为NULL*/
    		if (h==NULL)/*如果h=NULL,表示当前在处理第一个结点*/
    		{
    			h=cur;/*令h指向第一个结点*/
    		}
    		else
    			prev->next=cur;
    			/*令表中最后一个结点的next指向cur;prev负责将链段尾结点和新结点连起来*/
    			/*关于指针指来指去,想想就好了,实际上指针都是地址,内存条里是不会有箭头的。要懂链表,先理解结构体。结构体变量可以通过变量名.成员名的方式访问成员,也可以用存储了结构体首地址的指针变量->成员名的形式访问成员。这里cur存储了新来的结构体的首地址,prev存储了链段尾结构体的首地址,你不妨将指针直接看成结构体,没什么不妥。那么让尾结构体的指针成员next存储新来的结构体的首地址,这样,通过链段尾结构体就可以访问新来的结构体的了,事实上只能这样访问,别无它法。正因为如此,一个结构体带一个结构体,才起名为链表。
    			通过prev->next就可以操作指针成员next。prev->next=cur执行后,prev就存储了新来结构体的首地址。由于新来的结构体已经安顿好了,它其实已经作为老结构体了,那么prev就存储了这个老结构体的首地址,你可以把prev看成这个老结构体。
    			*/
    		//input information
    		printf("=====第%d人=====
    ",i+1);
    		input(cur);
    
    		prev=cur;/*将prev指向最后一个结点;prev永远指向链段的最后一个结点*/
    	}
    	return h;
    }
    
    void DispList(LIST *h)
    {
    	LIST *p=h;
    	int i=0;
    	while(p!=NULL)
    	{
    		if(i==0)
    		{
    			printf("学号	姓名	地址
    ");//只显示一次
    			i=1;
    		}
    		printf("%d	%s	%s
    ",p->no, p->name, p->addr);
    		p=p->next;
    	}
    }
    
    LIST *InsertNode(LIST *h, LIST *s)
    {
    	LIST *pre, *p;
    	p=h;
    	if (h==NULL)
    	{
    		h=s;
    		s->next=NULL;
    	}else{
    		while((s->no > p->no) && (p->next!=NULL))
    		{
    			pre=p;
    			p=p->next;
    		}
    		if(s->no <= p->no){
    			if (h==p){
    				s->next=h;
    				h=s;
    			}else{
    				pre->next=s;
    				s->next=p;
    			}
    		}else{
    			p->next=s;
    			s->next=NULL;
    		}
    	}
    	return h;
    }
    
    LIST *DeleteNode(LIST *h, long no)
    {
    	LIST *pre, *p;
    	if (h==NULL)
    	{
    		printf("链表为空,不能删除结点!
    ");
    		return NULL;
    	}
    	p=h;
    	while((p->no != no) && p->next!=NULL)
    	{
    		pre=p;
    		p=p->next;
    	}
    	if (p->no==no)
    	{
    		if (p==h)
    			h=p->next;
    		else pre->next=p->next;
    		free(p);
    		printf("结点成功删除
    ");
    	}else printf("There isn't Id:%d.
    ",no);
    	return h;
    }
    
    
  • 相关阅读:
    【LeetCode】085. Maximal Rectangle
    哈希查找
    堆排序
    归并排序
    希尔排序
    快速排序
    堆区和栈区,malloc和new的区别
    C++基础
    二分查找
    冒泡排序
  • 原文地址:https://www.cnblogs.com/feicaixian/p/9728631.html
Copyright © 2020-2023  润新知