线性表--------链表

1.创建一个链表


通过上述代码可以建立一条长度为n 的链表,实现流程如下:


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


(2)如果指针变量list为空,则说明本次生成的结点是第一个结点,
为此将p赋值给list。变量list 是LinkList类型的,只用来指向第-个链表结点,
因此它是该链表的头指针,最后要返回。


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


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


(5)最后,将生成的链表的头指针list 返回主调函数,通过list就可以访问到该链表的
每一个结点,并对该链表进行操作。

LinkList GreatLinkList(int n)
{
//建立一个长度为n的链表
LinkList p,r,list=NULL;
ElemType e;
int i;
for(i=1;i<=n;i++)
{
   Get(e);
   p=(LinkList)malloc(sizeof(LNode));
   p->data=e;
   p->next=NULL;
   if(!list)
      list=p;
    else
     r->next=p;
   r=p;	 
}
return list;
}

2.向链表中插入结点


在指针q指向的结点后面插入结点的流程如下:


(1)首先生成一个新的结点,大小为sizeof(LNode),用LinkList类型的变量p指向该结点,
并将该结点的数据域赋值为e。


(2)然后判断链表是否为空。如果链表为空,则将p赋值给list,p的next域的值置为
空;如果链表不为空,将q指向结点next域的值赋给p指向结点的nextyu,这样p指向
的结点就与q指向结点的下一个结点链接到了一起


(3)接下来将p的值赋值给q所指向结点的next域,这样就将p指向的结点插入到了指
针q指向结点的后面。

void insertList(LinkList *list,LinkList q,ElemType e)
{
     //向链表中由指针q指出的结点后面插入结点,结点数据为e
       LinkList p;
	   p=(LinkList)malloc(sizeof(LNode));   //生成一个新的结点,由p指向它
	   p->data=e;                            //向该结点的数据域赋值e
	   if(!*list)
	   {
	    *list=p;
		p->next=NULL;
	   }
	   else    //当链表为空时
	   {
	        p->next=q->next;
			//将q指向的结点next域的值赋值给p指向结点的next域
			q->next=p;
			//将p的值赋值给q的next域
	   }
}
3.从链表中删除结点


要从非空链表中删除q所指的结点,需要从如下3种情况情形来考虑。


(1)q所指结点是链表的第一个结点。
当q所指向的链表是第一个结点时,只需将q所指结点的指针域next的值赋值给头
指针list,让list指向第二个结点,然后再释放掉q所指向结点即可实现。


(2)q所指结点的前驱结点的指针是已知的。
当q所指结点的前驱结点的指针是已知时,在此假设为r,只需将q所指结点的指针域
next的值赋值给r的指针域next,然后释放掉q所指结点即可实现。
以上两种情形可用下面的代码来描述

void delLink(LinkList *list,LinkList r,LinkList q)
{
    if(q==*list)   //删除链表结点的第一种情形
	  *list=q->next;
	else
	   r->next=q->next;   //删除链表结点的第二种情形
	free(q);
}
(3)q所指结点的前驱结点的指针是未知的。
q所指结点的前驱结点的指针是未知时,需要先通过链表头指针list遍历链表,找到q的前驱结点的指针,
并将指针赋值给指针变量r,再按照第二种情形取做即可实现。

void delLink(LinkList *list,LinkList q)
{
    LinkList r;
	if(q==list)
	{
	*list=q->next;
	free(q);
	}
	else
	{
	   for(r=*list;r->next!=q;rr=r->next);
	   //遍历链表,找到q的前驱结点的指针
	   if(r->next!=NULL)
	   {
	      r->next=q->next;
		  free(q);
	   }
	}
}
4.销毁一个链表


实现流程如下:


(1)将链表*list的内容赋值给p,这样因为p指向链表的第一个结点而成为了链表的表头。


(2)只要p不为空(NULL),就将p指向的下一个结点的指针(地址)赋值给q,并使用函数
free()稀释掉p所指向的结点,p再指向下一个结点。重复上述循环,直到链表为空为止。


(3)最后将链表*list的内容置为空(NULL),此时主函数中的链表list就变为空,这样
防止list成为野指针,并且链表在内存中也被完全稀释掉了

void destroyLinkList(LinkList *list)
{
    LinkList p,q;
	p=*list;
	while(p)
	{
	  q=p->next;
	  free(p);
	  p=q;
	}
	*list=NULL;
}
链表操作实现


#include<stdio.h>
typedef struct
{
   char key[15];   //关键字
   char name[20];
   int age;
}DATA;
#include "2-4 ChainList.h"
#include "2-5 ChainList.c"
void ChainListAll(ChainListType *head)  //遍历链表  
{  
   ChainListType *h;
   DATA data;
   h=head;
   printf("链表所有数据如下:\n");   //循环处理链表每个结点
   while(h)                        
   {
     data=h->data;                   //获取结点数据
     printf("(%s,%s,%d)\n",data.key,data.name,data.age);  
	 h=h->next;                          //处理下一个结点
   }
}  
  
  
void main()  
{  
   ChainListType *node,*head=NULL;  
   DATA data;
   char key[15],findkey[15]; 
     
     printf("输入链表中的数据,包括关键字,姓名,年龄,关键字输入0则退出:\n");
   do{                                                
     fflush(stdin);                              //清空输入缓冲区  
     scanf("%s",data.key);  
	 if(strcmp(data.key,"0")==0) break;               //若输入0则退出
	  scanf("%s%d",data.name,&data.age);  
	  head=ChainListAllEnd(head,data);                 //在链表尾部添加结点数据
    
   }while(1);  
   
   printf("该链表共有%d个结点。\n",ChainListLength(head));   //返回结点数量
   ChainListAll(head);                                        //显示所有结点
   
   printf("\n插入结点,输入插入位置的关键字:");
   scanf("%s",&findkey);                                        //输入插入位置的关键字
   printf("输入插入结点的数据(关键字 姓名 年龄):");
   scanf("%s%s%d",data.key,data.name,&data.age);                //输入插入结点的数据
   head=ChainListInsert(head,findkey,data);                   //调用插入函数
   
   ChainListAll(head);                  //显示所有结点
   
   printf("\n在链表中查找,输入查找关键字:");
   fflush(stdin);                 //清空输入缓冲区
   scanf("%s",key);                   //输入查找关键字
   node=ChainListFind(head,key);        //调用查找幻术,返回结点指针
   if(node)                           //若返回结点指针有效
   {
      data=node->data;                 //获取结点的数据
	  printf("关键字%s对应的结点数据为(%s,%s,%d)\n",key,data.key,data.name,data.age);
   }
   else                                    //若指针无效
   {
    printf("在链表中未找到关键字%s的结点!\n",key);
   }
   printf("\n在链表中删除结点,输入要删除的关键字:");
   fflush(stdin);               //清空输入缓冲区
   scanf("%s",key);             //输入删除结点的关键字
   ChainListDelete(head,key);       //调用删除结点函数
   ChainListAll(head);              //显示所有结点
   getchar();  
}  


猜你喜欢

转载自blog.csdn.net/qq_41398448/article/details/80423891