链表

链表

可变数组

应具备的特点:
1、根据需求自动变大
2、知道它目前的大小
3、可以精确访问其中的元素
编写函数实现
将结构体Array当作一个数组使用

上代码

Array array_create(int init_size)//-->初始化结构(数组) 
void array_free(Array *a)// -->释放数组所占的空间
int array_size(const Array*a)//-->数组的长度
int* array_at(Array*a,int index)//-->定位数组中的某个元素
void array_inflate(Array*a,int more_size)//-->自动增加数组容量 
#include<stdio.h>
#include<stdlib.h>
typedef struct{
	int*array;
	int size;
}Array;
Array array_create(int init_size);//init_size为所传入数组的大小 
//另一种方法:
//Array array_create(Array*a,int init_size)//传入一个Array类型的指针,直接对一个结构操作。 
//{
//a->size = init_size;
//a->array = (int*)malloc(a->size*sizeof(int));
// } //这样的结构有风险:1、当传入的指针为NULL时  2、这个1指针可能曾经指向一个结构。要先用free()释放掉。 
void array_free(Array *a);
int array_size(const Array*a);
int* array_at(Array*a,int index);
void array_inflate(Array*a,int more_size);//创建一个新的空间(类似于array_create),来装原来装不下的数据,并释放掉原来的旧空间。 


int main()
{
	int longth;
	scanf("%d",&longth);
	Array a=array_create(longth);
	array_free(&a);
	printf("%d",array_size);
	

}

Array array_create(int init_size)
{
	Array a;
	a.size = init_size;
	a.array= (int*)malloc(a.size*sizeof(int));
	return a;//存在于array_create中,可以在主函数中声明一个Array类型的结构体初始化为array_create的返回值,以此完成创造结构体的目的。 
 } 
 
 
void array_free(Array *a)//传入定义好的结构,释放掉它所申请的内存 
{
free(a->array);
a->size = 0;
a->array = NULL;//防止第二次调用时程序崩溃,free一个空指针是无害的 
}


int array_size(const Array*a);//查看a数组的大小 (封装) 
{
	return a->size;
}


int* array_at(Array*a,int index)
{
return (a->array)+index;//或者&(a->array[index]) 
}
  

void array_inflate(Array*a,int more_size)
{
	int *p = (int*)malloc(sizeof(int)*(a->size+more_size));
	for(i = 0;i<a->size;i++)
	{
		   p[i] = a->array[i];
	}
	free(a->array); 
	a->array = p;
	a->size+=more_size;//更新这个数组,使之容纳更大的数据。 
 } 

可变数组的缺陷
1.每次都要新申请一块内存,然后再释放旧的内存,但此时系统的剩余内存可能不足以容纳新申请的内存(即使总内存足够)
2、每次更新都要复制原来的数据,花费时间多
解决方法:每次申请一块block大小的内存,并用指针指向这块内存,连接它们

所以链表代替它

//链表
#include<stdio.h>
#include<stdlib.h>
typedef struct Node{
	int value;
	struct Note*next;
}node; 
int main()
{
	node *head = NULL;
	int number;
	do{
		scanf("%d",&number);
		if(number != 1)
		{
		//添加链表 
		node *p = (node*)malloc(sizeof(node));//每次malloc出的地址不一样 
		p->value = number;
		p->next = NULL;
		 //找到最后一个 
		node *last = head;
		if(last != 0)
		{
			while(last->next != 0)
			last = last->next;
		//接近元素	
		    last->next = p;
		}
		else
			head = p;
		}
		 
	}while(number != -1);
	
	

return 0; 
}

链表中的每个结点实质是一个结构体,包含数据部分和指向下一个节点的指针。
链表的增删改查、头插法、尾插法

/链表


//链表的创建 

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct Note{
	char name[20];
	struct Note*next;
}note;

note* create()//创建链表 
{
	note *head,*current,*next;
		char str[10];
		char flag;
		printf("Please enter the name:");
		scanf("%s",str);
		getchar();//得到scanf时留在缓冲区的空格 
		head = (note*)malloc(sizeof(note));
		strcpy(head->name,str);
		
		current = head;
		printf("continue?");	
		scanf("%c",&flag);
		while(flag == 'Y')
		{
		scanf("%s",str);
		getchar();
		next =(note*)malloc(sizeof(note));
		strcpy(next->name,str);
		next->next = NULL; 
		current->next = next;//链接两个结点 
		//上一个元素的指针指向下一个元素 
		current = next;//移动current,让他指向next(类比于指针的++p) 
		printf("continue?");
		scanf("%c",&flag);
		}
		return head;//返回的是链表的首地址 
		} 

void list(note*p)//遍历链表并打印内容 
{
		
		while(1)
		{
			printf("%s\n",p->name);
			
			if(p->next != NULL)	
			{
				p = p->next;
			}
			else
			break;
			}
	}
void insert(int position,note**p)//链表的插入函数//传入指针的地址来修改指针所指//当修改结构里的指针时,传入指向这结构体的指针 
{	
	note *head,*backward;
	backward = *p;
	char str[10];

	printf("Please enter a insert name:  ");
	scanf("%s",str);
	getchar();
	
	head = (note*)malloc(sizeof(note));
	strcpy(head->name,str);
	
	if(position)
	{
	for(int i =1;i<position;i++)
	{	
		backward = backward->next;
	}	
	head->next = backward->next;//插入元素指向后一个元素
	backward->next = head;//上一个指向插入元素  
	}
	else
	{
		*p = head;
		head->next = backward;
	}
	
	}

void link_delete(int position,note**p)
{
	note *backward;
	backward = *p;
	if(position)
	{
	for(int i = 1;i<=position;i++)
		backward = backward->next;
		
		*p = backward->next;
		free((*p)->next);
		}
		else
		{
		*p = (*p)->next;
		free(backward);
		}
}	

	int main()
	{
		note*p = create();
		insert(0,&p);
		link_delete(0,&p); 
		list(p); 
		return 0;
	}
	

链表的插入
新建一个元素,让指定插入位置的前一个元素指向要插入的元素
再让要插入的元素指向它的后一个元素

具体操作:让前一个元素的指针指向待插入元素,再让待插入元素指向后一个元素

头插法

把后建立的结点插在头部。用这种方法建立起来的链表的实际顺序与输入顺序刚好向反,输出时为倒序!
s->Data=x; //数据域插入的值

s->Next=L->Next;          
L->Next=s;            
第一个结点的指针域,等于头指针的指针域等于NULL,表示链尾。然后将节点插入到链表中,这两步的顺序一定不能相反。

//

代码如下

LinkList CreateList_Head(LinkList L)
{
	LinkList s;int x;
	L = (LNode*)malloc(sizeof(LNode));     //创建头结点 
	L->Next=NULL;                          
	scanf("%d",&x);                       
	while(x!=9999){                             
		s=(LNode*)malloc(sizeof(LNode));  
		s->Data=x;                           
		s->Next=L->Next; //在第二次循环时将第二个数据插到刚开始的两个数据之间                     
		L->Next=s;                          //插入结点
		scanf("%d",&x);
	}
	return L;
}

有关的好的文章
C语言数据结构之链表的增删改查——wrlovesmile

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值