• 1.3链表


    链表的物理存储结构是用一组地址任意的存储单元存储数据的。不像顺序表占据连续的一段内存空间,而是将存储单元分散在内存的任意地址上。

    链表结构中,每个数据元素记录都存放到链表的一个节点(node)中,而每个节点之间由指针将其连接在一起,形成了”链“的结构、

    链表每个节点中,都必须有一个专门用来存放指针(地址)的域,用这个指针域来存放后继结点的地址,这样就达成了连接后继结点的目的。

    一条链表通常有1个”表头“,是一个指针变量,用来存放第一个节点地址。此外,一条链表的最后一个节点的指针域要置空(NULL),表示该节点为链表的尾节点,因为它之没有后继结点了。

    链表特征:

    1)每个节点包括两部分:数据域和指针域。其中数据域用来存放数据元素本身的信息,指针域用来存放后继结点的地址。

    2)链表逻辑上是连续的,而物理上不一定连续存储节点、

    3)只要获得链表的头节点,就可以通过指针遍历整条链表。

    实例:编写一个程序,要求:从终端输入一组整数(大于10个数),以0作为结束标志,将这一组整数存放在一个链表中,(结束标志0不包括在内),打印出该链表中的值。然后删除该链表中的第五个元素,打印出删除后的结果。最后在内存中释放掉该链表。

    #include"stdio.h"
    #include"stdlib.h"
    typedef int ElemType;
    
    typedef struct node{
    	ElemType data;
    	struct node *next;
    }LNode,*LinkList;
    	
    LinkList GreatLinkList(int n) {	//创建一个长度为n的链表 
    	LinkList p,r,list=NULL;
    	ElemType e;
    	int i;
    	for(i=1;i<=n;i++) {
    		scanf("%d",&e);		//输入结点的内容 
    		p=(LinkList)malloc(sizeof(LNode));//为新建的结点开辟内存空间 
    		p->data=e;			//元素赋值 
    		p->next=NULL;
    		if(!list)
    			list=p;			//赋值链表头指针 
    		else
    			r->next=p;		//将结点连入链表 
    		r=p;
    	}
    	return list;		//返回链表头指针 
    }
    
    void insertList(LinkList *list,LinkList q,ElemType e) {//向链表中插入结点 e 
    	LinkList p;
    	p=(LinkList)malloc(sizeof(LNode));//为新建的结点开辟新的内存空间 ,生成一个新结点,由p指向它 
    	p->data=e;					//向该结点的数据域赋值e 
    	if(!*list) {
    		*list=p;			//list内容为NULL时,表示该链表为空,赋值链表头指针 
    		p->next=NULL;
    	}					//当链表为空时q没有意义,只能在头结点后面插入第一个元素 
    	else {
    		p->next=q->next;//当链表不为空时,认为q指向的结点一定存在,将q指向的结点的next域的值赋给p指向结点的next域
    		q->next=p;	
    	}
    }
    
    void delLink(LinkList *list,LinkList q) {	//删除链表的某结点 
    	LinkList r;
    	if(q==*list) {	//如果删除第一个结点 
    		*list=q->next;
    		free(q);
    	}
    	else {			//删除其他结点 
    		for(r=*list;r->next!=q;r=r->next)
    			if(r->next!=NULL) {
    				r->next=q->next;
    				free(q);
    			}
    	}
    }
    
    void destroyLinkList(LinkList *list) {	//销毁一个链表 
    	LinkList p,q;
    	p=*list;
    	while(p) {	//循环释放掉每一个链表结点 
    		q=p->next;
    		free(p);
    		p=q;
    	}
    	*list=NULL;//将*list的内容置为NULL,这样主函数中的链表list就为空,防止了list变为野指针,而且链表在内存中也完全被释放掉了。
    }
    
    int main() {
    	int e,i;
    	LinkList l,q;
    	q=l=GreatLinkList(l);//创建一个链表结点,q和l都指向该结点 
    	scanf("%d",&e);
    	while(e) {			//循环输入数据,同时插入新生成的结点 
    		insertList(&l,q,e);
    		q=q->next;
    		scanf("%d",&e);
    	}
    	q=l;
    	printf("the content of the linklist
    ");
    	while(q) {			//输出链表中的内容 
    		printf("%d",q->data);
    		q=q->next;
    	}
    	q=l;
    	printf("
    Delete the fifth element");
    	for(i=0;i<4;i++) { //将指针q指向链表的第五个元素 
    		if(q==NULL) {	//确保此时链表的长度大于等于5,否则将是非法操作 
    			printf("the length of the linklist is  smaller than 5!");
    			
    		}
    		q=q->next;
    	}
    	delLink(&l,q);	//找到链表中第五个元素,用q指向它,再删除q所指的结点 
    	q=l;
    	while(q) {		//打印出删除后的结果 
    		printf("%d",q->data);
    		q=q->next;
    	}
    	destroyLinkList(&l); 	//销毁该链表 
    	return 0;
    }
    

      

    创建链表注意:

    (1)用malloc()函数在内存的动态存储区(堆内存)中开辟一块大小为sizeof(LNode)的空间,并将其地址赋给LinkList类型变量p,(LinkList为指向LNode变量的类型,LNode为前面定义的链表结点类型)。然后将数据e存入该结点的数据域data,指针域存放NULL。

    (2)若指针变量list为空,说明本次生存的结点是第一个结点……

    (3)若指针变量list不为空,说明本次生存的结点不是第一个结点,将p赋给r->next。此处的r是一个LinkList类型变量,永远指向原先链表的最后一个结点,也就是要插入结点的前一个结点。

    (4)再将p赋值给r,目的是使r再次指向最后的结点,以便生成链表的下一个结点,即保证r永远指向原先链表的最后一个结点。

    (5)重复(1)~(4)n次,生成n个结点的链表

    (6)最后生成的链表的头指针list返回主调函数,通过list就可以访问到该链表的每一个结点。

    删除链表注意:

    从非空链表删除q所指的结点,考虑3种情况:

    (1)q所指向的是链表的第一个结点

    (2)q所指向的结点的前驱结点的指针已知

    (3)q所指向的结点的前驱结点的指针未知

    销毁链表注意

    链表使用完建议销毁,因为链表本身会占用内存空间。若一个系统中使用很多链表,而使用完又不及时销毁,那么这些垃圾空间积累过多,最终导致内存的泄露甚至程序的崩溃。

    ————————————————————————

    ————————————————————————

    程序运行时候,删除第5个元素,没有显示出预期结果。运行环境在DEV。

    拥抱明天! 不给自己做枷锁去限制自己。 别让时代的悲哀,成为你人生的悲哀。
  • 相关阅读:
    bzoj1607: [Usaco2008 Dec]Patting Heads 轻拍牛头
    bzoj1016: [JSOI2008]最小生成树计数
    bzoj1051: [HAOI2006]受欢迎的牛
    bzoj1003: [ZJOI2006]物流运输
    bzoj1079: [SCOI2008]着色方案
    bzoj1179: [Apio2009]Atm
    bzoj1877: [SDOI2009]晨跑
    bzoj1821: [JSOI2010]Group 部落划分 Group
    bzoj1305: [CQOI2009]dance跳舞
    bzoj1858: [Scoi2010]序列操作
  • 原文地址:https://www.cnblogs.com/dd2hm/p/6838694.html
Copyright © 2020-2023  润新知