链表

这样一种存储方式,其存储元素的个数是不受限定的,当进行添加元素时,存储的个数就会随之改变,这种存储方式就是链表。

链表中有一个头指针变量,head就是头指针,在这个指针变量中保存一个地址。这个地址为一个变量的地址。这个变量称为元素。

一个元素包裹两部分:数据部分和指针部分

1.单链表的建立

动态创建一个节点时,要为其分配内存。

malloc()函数:void *malloc(unsighned int size);

该函数的作用就是在内存中动态的分配一块size大小的内存空间。malloc函数返回一个指针,该指针指向分配的内存空间,若出现错误,则返回NULL

calloc()函数:void *calloc(unsighned int n,unsighned int size);
该函数就是n个长度为size的连续内存空间数组。calloc会返回这样一个指针,该指针指向动态分配的内存空间的地址。
free()函数:void free(void *ptr);
free函数无返回值
该函数的功能是使由指针ptr指向的内存区,使部分内存区能被其他变量使用。

2.单链表表的插入、删除

以下为完整的链表操作实例

 

 

//完整的链表操作代码
#include<stdio.h>
#include<stdlib.h>
struct Student 
{
	char cName[20];//姓名 
	int iNumber;	//学号
	struct Student* pNext; 
};
int iCount;//全局变量表示链表长度
struct Student* Create()
{
	struct Student* pHead=NULL;//初始化链表头指针为空 
	struct Student* pEnd,*pNew;
	iCount=0; //初始化链表长度 
	pEnd=pNew=(struct Student*)malloc(sizeof(struct Student));
	printf("首先输入姓名,然后输入学号\n");
	scanf("%s",&pNew->cName);
	scanf("%d",&pNew->iNumber);
	while(pNew->iNumber!=0)
	{
		iCount++;
		if(iCount==1)
		{
			pNew->pNext=pHead;//使得指向为空
			pEnd=pNew;//跟踪新加入的节点 
			pHead=pNew; //头指针指向首节点 
		}
		else
		{
			pNew->pNext=NULL;
			pEnd->pNext=pNew;
			pEnd=pNew;
		 } 
		 pNew=(struct Student*)malloc(sizeof(struct Student));//再次分配节点内存空间
		scanf("%s",&pNew->cName);
		scanf("%d",&pNew->iNumber);
	}
	free(pNew); //释放没有用dao的空间
	return pHead; 
	
} 
void Print(struct Student* pHead)
{
	struct Student *pTemp;   //循环所用的临时指针
	int ilndex=1; //表示链表中节点的序号
	printf("---这个链表中有%d个成员:-----\n",iCount);//消息提示
	printf("\n");
	pTemp=pHead;
	while(pTemp!=NULL)
	{
		printf("member %d is \n",ilndex);
		printf("name %s is\n",pTemp->cName);
		printf("number %d is\n",pTemp->iNumber);
		printf("\n");
		pTemp=pTemp->pNext;
		ilndex++;
	}
}
struct Student* Insert(struct Student* pHead)
{
	struct Student* pNew;
	printf("--首先插入一个成员--\n");
	pNew=(struct Student*)malloc(sizeof(struct Student));
	scanf("%s",&pNew->cName);
	scanf("%d",&pNew->iNumber);
	pNew->pNext=pHead;
	pHead=pNew;
	iCount++;
	return pHead;
	
}
void Delete(struct Student* pHead,int ilndex)
{
	int i;//控制循环变量
	struct Student *pTemp; //临时指针 i
	struct Student *pPre; //..删除节点钱的节点
	pTemp=pHead;//得头节点
	pPre=pTemp;
	printf("删除地%d个成员\n",ilndex);
	for(i=1;i<ilndex;i++)
	{
		pPre=pTemp;
		pTemp=pTemp->pNext;
	 } 
	 pPre->pNext=pTemp->pNext;
	 free(pTemp);
	 iCount--;
	 

}
main()
{
	struct Student *pHead;
	pHead=Create();
	pHead=Insert(pHead);
	Delete(pHead,2);
	Print(pHead);
	return 0;
}

离散 298990
张思 898989
王五 334343
李六 334342

 

力气 232323

//合并两个链表操作实例

//合并两个链表 
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
typedef struct student 
{
	int num;
	struct student *next;
}LNode,*LinkList;
LinkList create()
{
	LinkList head;
	LNode *p1,*p2;
	char a;
	head=NULL;
	a=getchar();
	while(a!='\n')
	{
		p1=(LNode*)malloc(sizeof(LNode)); //分配空间
		p1->num=a;
		if(head==NULL)
		{
			head=p1;
		} 
		 else
		 {
		 	p2->next=p1;
	    }
		p2=p1;
		a=getchar(); 
	}
	p2->next=NULL;
	return head;
}
LinkList coalition(LinkList L1,LinkList L2)
{
	LNode *temp;
	if(L1==NULL)
	{
		return L2;
	}
	else
	{
		if(L2!=NULL)
		{
			for(temp=L1;temp->next!=NULL;temp=temp->next);//遍历L1知道尾节点 
			temp->next=L2;
		}
	}
	return L1; 
}
main()
{
	LinkList L1,L2,L3;
	printf("please input two chains:\n");
	printf("The number one chain is :\n");
	L1=create();
	printf("The number two chain is:\n");
	L2=create();
	coalition(L1,L2);
	printf("合并后的链表是:\n");
	while(L1)
	{
		printf("%c  ",L1->num);
		L1=L1->next;	
	 } 
	 getch();
	 
}

 

 

 

 

3.循环链表

链表中最后一个节点的指针域指向头节点,使链表形成一个环,从表中任意一个节点出发,均可以找到其他节点。与普通链表相比,只是在算法中循环遍历链表节点时,判断条件不是p->next==NULL,而是p->next==head

 

#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
typedef struct student 
{
	int num;
	struct student *next;
}LNode,*LinkList;
LinkList create()
{
	LinkList head;
	LNode *p1,*p2;
	char a;
	head=NULL;
	a=getchar();
	while(a!='\n')
	{
		p1=(LNode*)malloc(sizeof(LNode)); //分配空间
		p1->num=a;
		if(head==NULL)
		{
			head=p1;
		} 
		 else
		 {
		 	p2->next=p1;
	    }
		p2=p1;
		a=getchar(); 
	}
	p2->next=head;
	return head;
}
main()
{
	LinkList L1,head;
	puts("please create a chain\n");
	L1=create();
	head=L1;
	printf("This chain is:\n");
	printf("%c ",L1->num);
	L1=L1->next;
	while(L1!=head)
	{
			printf("%c ",L1->num);
			L1=L1->next;
	}
	printf("\n");
}

 

 

 

4.chuang'jian's

创建双向链表

//创建双向链表,将链表中的数据输出到窗体上,然后输入要查找学生的姓名,将学生姓名熊表中删除,并显示删除后的链表
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct node
{
	char name[20];
	struct node *prior,*next;
 }stud;
 stud *create(int n)
 {
 	stud *p,*h,*s; //p时当前节点,h时头节点,s是临时节点 
 	int i;
 	h=(stud*)malloc(sizeof(stud));
 	h->name[0]='\0';
 	h->prior=NULL;
 	h->next=NULL;
 	p=h;
 	for(i=0;i<n;i++)
 	{
 		s= (stud*)malloc(sizeof(stud));
 		p->next=s;
 		printf("输入第%d个学生的姓名:",i+1);
		scanf("%s",&s->name); 
 		s->prior=p;
 		s->next=NULL;
 		p=s;
	 }
	 p->next=NULL;
	 return (h);
 }
 stud *search(stud *h,char *c)
 {
 	stud *p;
 	char *y;
 	p=h->next;
 	while(p)
 	{
		y=p->name;
 		if(strcmp(y,c)==0)
 		{
 			return (p);
		 }
		 else
		 {
		 	p=p->next;
		 }
	 }
	 puts("no this node\n");
 }
 void del(stud *p)
 {
 	p->next->prior=p->prior;
 	p->prior->next=p->next;
 	free(p);
 }
 main()
 {
 	int number;
 	char sname[20];
 	stud *head,*sp;
 	puts("please input the size of chain:\n");
 	scanf("%d",&number);
 	head=create(number);
 	sp=head->next;
 	printf("现在这个双链表是:\n");
	while(sp)
	{
		printf("%s  ",&*sp->name);
	 	sp=sp->next;
	 } 
	 printf("\n请输入你要查找的名字:\n");
	 scanf("%s",sname);
	 sp=search(head,sname);
	 printf("\n你想查找的姓名是%s:\n",*&(sp->name));
	 del(sp);
	 sp=head->next;
	 puts("现在的双链表是:\n"); 
	 while(sp)
	 {
	 	printf("%s   ",&*(sp->name));
	 	sp=sp->next;
	 }
	 printf("\n");
	 puts("\nany key to exit..."); 
	 
 }

 

 

这里面还涉及到一个c的知识点,关于typedef

c语言不仅提供了丰富的数据类型,还允许用户自己定义 类型说明符。

即 允许由用户  为数据类型  取“别名”。类型定义符tyoedef就是这个功能

typedef 原类型名 新类型名

类似上面的例子中,结构的结构名为LNode和LinkList,

那么就可以直接用结构名 定义结构体变量

 

即typedef可以声明各种类型名,但是不可以定义变量。

eg:typedef int ARR[10];

ARR a,b,c;   代表定义的数组a,b,c,分别都含有十个元素。

typedef int INTEGER;   INTEGER i;代表定义的i为int类型。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值