数据结构基本概念、顺序表和单链表(数据结构一)

一.数据结构

1.概念

数据结构研究的是存储位置的使用技巧

2.数据结构的两种角度

一个角度是数据在人的认识中的关系,这种关系叫做数据间的逻辑关系(逻辑结构)

另一个角度是数据在计算机内部存储时他们之间关系,这种关系叫丛数据间的物理关系(物理结构)

(1)逻辑结构的分类

集合: 所有数据看成一个整体,数据之间没有特殊的联系

线性结构: 所有的数据可以看成一条直线,数据之间存在一对一的关系

树状结构(层次结构): 在线性结构的基础上允许数据有多个跟随数据,数据之间存在一对多的关系

网状结构(图): 任何两个数据之间都可以有直接联系,数据之间存在多对多的关系

(2)物理结构的分类

顺序结构: 所有的数据在内存中连续排列,通常通过数组/动态内存来实现。

顺序结构可以随时找到任意一个数据,具有随机访问能力,便于查找和修改

不便于进行增加和删除,使用时不能调整大小,容易造成空间浪费

链式结构: 多个数据之间相互独立,有联系的数据之间用指针连接

链式结构通常使用结构体来实现,每个结构体数据叫做一个节点

链式结构便于增加和删除,为了实现增加时分配内存,删除时释放内存,节点的空间使用动态内存分配

链式结构没有随机访问能力,不便于查找和修改
在这里插入图片描述
逻辑结构和物理结构互不影响,任何一种逻辑结构可以用任何一种物理结构来实现

数据结构实现的是多个相关数据的管理功能,分为2个部分:

①多个相关的存储位置,通常就是提供一个结构体

②提供一组相关函数,这些函数可以让使用者以某种方式使用以上的存储位置(增删改查 创建 销毁 遍历)

二.顺序表

顺序表就是使用顺序结构实现的线性结构

定义sqlist.h

#ifndef _SQLIST_H_
#define _SQLIST_H_

#define N 100

typedef int T;

typedef struct sqlist{
    T data[N];//存放需要存储的数据
    int last;//记录数据个数
}sqlist_t,*sqlink_t;

sqlink_t init_sqlist();//初始化顺序表
void insert_by_index(sqlink_t sq,T index,T dt);//按位置添加
void delete_by_index(sqlink_t sq,T index);//按位置删除
void insert_tail(sqlink_t sq,T dt);//在尾部添加
void delete_tail(sqlink_t sq);//在尾部删除
void look(sqlink_t sq);//遍历顺序表
int search_by_value(sqlink_t sq,T dt);//按值查找(只查找第一个)
int search_by_index(sqlink_t sq,T index);//按位置查找
void change_by_index(sqlink_t sq,T index,T dt);//按位置修改
void change_by_value(sqlink_t sq,T value,T dt);//按值修改(修改所有)
void destroy_sqlist(sqlink_t *psq);//销毁顺序表

#endif

初始化顺序表

sqlink_t init_sqlist()
{
    sqlink_t sq = (sqlink_t)malloc(sizeof(sqlist_t));
    if(sq!=NULL){
        //初始化数据个数为0
        sq->last = 0;
    }

    return sq;
}

销毁顺序表

void destroy_sqlist(sqlink_t *psq)
{
    free(*psq);
    *psq = NULL;
}

按位置添加

void insert_by_index(sqlink_t sq,T index,T dt)
{
	T i;
	if(sq)
	{
		if(index<0||index>sq->last)
			printf("out of range!\n");
		else if(sq->last>=N)
			printf("sqlist is full!");
		else
		{
			for(i=sq->last;i>index;i--)
				sq->date[i]=sq->date[i-1];
			sq->date[index]=dt;
			sq->last++;
		}
	}
	else
		printf("sqlist is NULL!\n");
}

按位置删除

void delete_by_index(sqlink_t sq,T index)
{
	T i;
	if(sq)
	{
		if(index<0||index>=sq->last)
			printf("out of range!\n");
		else
		{
			for(i=index;i<sq->last;i++)
				sq->date[i]=sq->date[i+1];
			sq->last--;
		}
	}
	else
		printf("sqlist is NULL!");
}

在尾部添加

void insert_tail(sqlink_t sq,T dt)
{
	if(sq)
		sq->date[sq->last++]=dt;
	else
		printf("sqlist is full!\n");
}

在尾部删除

void delete_tail(sqlink_t sq)
{
	if(sq)
		sq->last--;
	else
		printf("sqlist is null!\n");
}

按位置查找

int search_by_index(sqlink_t sq,T index)
{
	if(sq)
	{
		if(index<0||index>sq->last)
			return -ENOINDEX;
		else
			return sq->date[index];
	}
	else
	{	
		printf("sqlist is NULL!");
		return -ENULL;
	}	
}

按值查找(只查找第一个)

int search_by_value(sqlink_t sq,T dt)
{
	T i;
	if(sq)
	{
		for(i=0;i<sq->last;i++)
		{
			if(sq->date[i]==dt)
				return i;
		}
				return -ENOMEM;
	}
	else
	{	
		printf("sqlist is NULL!");
		return -ENULL;
	}
}

按位置修改

void change_by_index(sqlink_t sq,T index,T dt)
{
	if(sq)
	{
		if(index<0||index>sq->last)
			printf("out of range!\n");
		else
			sq->date[index]=dt;
	}
	else
	{	
		printf("sqlist is NULL!");
	}	
}

按值修改(修改所有)

void change_by_value(sqlink_t sq,T value,T dt)
{
	T i,falg;
	if(sq)
	{	
		for(i=0;i<sq->last;i++)
		{
			
			if(sq->date[i]==value)
			{
				sq->date[i]=dt;
				flag=0;
			}
		}
		
	}
	else	
		printf("sqlist is NULL!");
	if(flag==0)
		return 0;
	else
		return -ENOMEM;
}

遍历顺序表

void look(sqlink_t sq)
{
	T i;
	for(i=0;i<sq->last;i++)
	{
		printf("%d ",sq->date[i]);
	}
	printf("\n");
}

三.单链表

1.概念

链表是链式的线性结构

单向链表中任何一个节点只能沿着一个方向访问下一个节点

单链表的节点 (结构体) 包括数据域指针域,数据域存放节点存储的数据,指针域存放下一个节点的地址

单链表最后一个节点的指针域必须设置为NULL

通过单链表的第一个节点可以访问到链表的每一个节点,可以记录第一个节点的地址来代表整个链表

使用一个指针记录第一个节点的地址,这个指针叫头指针,可以用来代表整个链表

由于头指针表示法无法区分空链表和链表不存在,所以更倾向于使用头结点表示整个链表

头结点的指针域指向链表第一个节点,数据域不使用
在这里插入图片描述
如果需要频繁访问单链表的尾部,可以记录链表尾结点的地址

节点使用动态内存分配来分配空间,需要时申请,不需要时释放,不会造成空间浪费

方便进行插入和删除

单链表在头部操作效率较高,在尾部操作效率较低,如果我们频繁地在单链表的尾部进行操作,可以将单链表进行改进,将单链表改成单向循环链表

单向循环链表的最后一个节点的指针域指向头结点,记录最后一个节点的地址来代表单向循环链表

定义linklist.h

#ifndef _LINKLIST_H_
#define _LINKLIST_H_

typedef int T;

typedef struct node{
	T date;//数据域,存放节点的数据
	struct node *next;//指针域,指向下一个节点
}linknode_t,*linklist_t;

linklist_t creat_emptylist();//创建单链表
linklist_t insert(linklist_t p,T dt);//从指定位置之后插入
linklist_t insert_head(linklist_t head,T dt);//从头部插入
linklist_t insert_tail(linklist_t head,T dt);//从尾部插入
linklist_t serach_by_index(linklist_t head,T index);//按位置查找
linklist_t serach_by_date(linklist_t head,T dt);//按值查找
linklist_t delete_by_index(linklist_t head,int index);//按位置删除
linklist_t delete_by_date(linklist_t head,T dt);//按值删除
void clear(linklist_t head);//清空单链表
void look(linklist_t head);//遍历单链表
void destory(linklist_t *phead);//销毁单链表

#endif

创建单链表

linklist_t creat_emptylist()
{
	linklist_t head=(linklist_t)malloc(sizeof(linknode_t));
	if(head)
	{
		head->next=NULL;//头节点的指针域指向NULL
		//head->date=-1;
	}
	return head;
}

从指定位置之后插入

linklist_t insert(linklist_t p,T dt)
{
	linklist_t newnode=(linklist_t)malloc(sizeof(linknode_t));//构造一个新节点
	if (newnode)
	{
		newnode->date = dt;
		newnode->next = p->next;
		p->next = newnode;
	}
	return newnode;
}

从头部插入

linklist_t insert_head(linklist_t head,T dt)
{
	return insert(head,dt);
}

从尾部插入

linklist_t insert_tail(linklist_t head,T dt)
{
	while(head->next)
	{
		head = head->next;
	}
	return insert(head,dt);
}

按位置查找

linklist_t serach_by_index(linklist_t head,T index)
{
	T i=0;
	head = head->next;
	while(head->next)
	{
		if(i==index)
			return head;
		head = head->next;
		i++;
	}
	return NULL;
}

按值查找

linklist_t serach_by_date(linklist_t head,T dt)
{
	head = head->next;
	while(head)
	{
		if(head->date==dt)
			return head;
		head = head->next;
	}
	return NULL;
}

按位置删除

linklist_t delete_by_index(linklist_t head,int index)
{	
	linklist_t p = NULL,delete_node = NULL;
	if(index<1)
	{
		printf("error index!\n");
		return NULL;
	}
	delete_node = serach_by_index(head,index);
	if(!delete_node)
		return NULL;
	if(index==1)
	{
		p = head;
	}
	else
		p = serach_by_index(head,index-1);
	//delete_node = p->next;
	p->next = delete_node->next;
	free(delete_node);
	delete_node = NULL;

	return p;
}

按值删除

linklist_t delete_by_date(linklist_t head,T dt)
{	
	linklist_t del_node = head;
	head = head->next;
	while(head)
	{
		if(head->date==dt)
			break;
		del_node = head;
		head = head->next;
	}
	if(!head)
		return NULL;
	del_node->next = head->next;
	free(head);
	head = NULL;
	return NULL;
}

遍历单链表

void look(linklist_t head)
{
	head = head->next;
	while(head)
	{
		printf("%d ",head->date);
		head = head->next;
	}
	printf("\n");
}

清空单链表

void clear(linklist_t head)
{
	linklist_t p = head->next,q = p;
	head->next = NULL;
	while(p)
	{
		q = p;
		p = p->next;
		free(q);
	}
	q = NULL;
}

销毁单链表

void destory(linklist_t *phead)
{
	clear(*phead);
	free(*phead);
	*phead = NULL;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java.L

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值