数据结构——线性表(Code)

下面写的代码可能感觉会很乱,所以加上了目录,意在为了引导,也就是你需要回顾哪个算法,就能够快速定位到该位置,如果从上往下去找的话,估计脑壳也疼死了。

一、线性表的基本操作

(一)顺序表的基本操作
1. 顺序表的结构体
#define MAX_SIZE 30				//设置顺序表最大容量
typedef struct
{
	int data[MAX_SIZE];			//设置数据最大长度
	int length;					//设置数据当前长度

}Sqlist;
2. 顺序表的查找
/*
method:
	顺序表的查找
param:
	L 顺序表
	n代表要查找的元素
*/

int Find_Elem(Sqlist L, int n)
{
	int result = 0;								//存放所查找到匹配值的下标
	for (result; result < n; result++)
	{
		if (L.data[result] == n)
			return result;
	}
	return ERROR;
}
3. 顺序表的插入
/*
method:
	顺序表的插入
param:
	sqlist 要操作的顺序表
	pos    要插入的位置
	data   要插入的数据
*/
int Insert_Elem(Sqlist* sqlist, int pos, int data)
{
	int i = 0;
	if (pos<0 || pos>sqlist->length || sqlist->length == MAX_SIZE)		//这里是判断 如果 查询位置不在线性表内,或者线性表长度满了,则返回Error
		return ERROR;
	for (i = sqlist->length-1; i >= pos; i--)							//这个循环将pos位置后面的元素由后往前向后挪1个位置
		sqlist->data[i+1] = sqlist->data[i];
	sqlist->data[pos] = data;											//插入设定值
	sqlist->length += 1;												//线性表长度加1
	return OK;
}
4. 顺序表的删除
/*
method:
	顺序表的删除
param:
	sqlist	要操作的顺序表
	pos		要删除的位置
	num		存放删除的元素
*/

int Delete_Elem(Sqlist* sqlist, int pos,int *num)						
{
	int i = pos;
	if (pos<0 || pos >sqlist->length)
		return ERROR;
	*num = sqlist->data[pos];											//得到删除的值
	for (i; i < sqlist->length; i++)									//由前往后,pos位置后面的值依次往前移动
		sqlist->data[i] = sqlist->data[i + 1];
	sqlist->length -= 1;												//线性表长度减1
	return OK;
}
5. 顺序表的更改
/*
method:
	顺序表的更改
param:
	sqlist	要操作的顺序表
	pos		要修改的位置
	num		要修改的值
*/

int Alter_Elem(Sqlist* sqlist, int pos, int num)
{
	if (pos<0 || pos >sqlist->length)									//判断范围
		return ERROR;
	sqlist->data[pos] = num;											//更改
	return OK;
}
(二)单链表的基本操作
1. 单链表的结构体
typedef struct LNODE
{
	int data;						//数据域
	struct LNODE* next;				//指针域
}LNODE;
2. 尾插法创建单链表
/*
method:
	尾插法创建单链表
param:
	lnode	要操作的顺序表
	dat		数组中存放要创建链表的数据
	n		要创建单链表的长度
*/
int Create_Lnode_Tail(LNODE* lnode, int dat[], int n)
{
	LNODE* p, * q;
	int i = 0;
	//lnode = (LNODE*)__vcrt_malloc_normal(sizeof(LNODE));		//创造头节点
	lnode->data = NULL;											//初始化头节点
	lnode->next = NULL;								
	p = lnode;
	for (i; i < n; i++)
	{
		q = (LNODE*)__vcrt_malloc_normal(sizeof(LNODE));		//创建新结点
		q->data = dat[i];										//接收数组元素
		p->next= q;												//尾插法核心
		p = p->next;
	}
	p->next = NULL;												//表尾
	Show_Lnode_data(lnode);										//遍历单链表元素
	return OK;
}
3. 头插法创建单链表
/*
method:
	头插法创建单链表
param:
	lnode	要操作的顺序表
	dat		数组中存放要创建链表的数据
	n		要创建单链表的长度
*/
int Create_Lnode_Head(LNODE* lnode, int dat[], int n)
{
	int i = 0;
	LNODE* q;
	//lnode = (LNODE *)malloc(sizeof(LNODE));					//给lnode指针分配内存空间
	lnode->data = NULL;											//初始化头结点
	lnode->next = NULL;
	for (i; i < n; i++)
	{
		q = (LNODE*)malloc(sizeof(LNODE));						//创建新结点
		q->data = dat[i];										//接收数组元素
		q->next = lnode->next;									//头插法的核心
		lnode->next = q;
	}
	Show_Lnode_data(lnode);

	return OK;
}
4. 遍历单链表
/*
method:
	遍历单链表的数据
param:
	lnode	要操作的顺序表
*/
void Show_Lnode_data(LNODE* lnode)
{
	LNODE* p = lnode;											//p指向单链表的头结点
	printf("%p", lnode);										//打印出来头结点指针的地址
	while (p->next != NULL)										//判断下一个结点是否为空
	{
		printf("->%d", p->next->data);							//打印出来链表中的数据
		p = p->next;											//遍历单链表
	}
	printf("\n");							
}
5. 合并两个单链表
/*
method:
	遍历单链表的数据
param:
	A	要操作的顺序表
	B	要操作的顺序表
	C	存放合并后的单链表
*/
void Merge_Lnode(LNODE* A, LNODE* B, LNODE** C)					//这里取指针的指针
{
	LNODE* a = A->next, * b =B->next, * c ;	
	*C = A;														//将A的存储空间的地址给*C
	(*C)->next = NULL;											
	__vcrt_free_normal(B);										//释放掉B的所占的存储空间
	c = *C;														//指针c指向头结点C
	while (a != NULL && b != NULL)								//判断这两个结点大小
	{
		if (a->data > b->data)
		{
			c->next = b;										//链接单链表
			b = b->next;										//取下一个结点
			c = c->next;										//始终表示最后一个结点的存储空间
		}
		else
		{
			c->next = a;										//链接单链表
			a = a->next;										//取下一个结点
			c = c->next;										//始终表示最后一个结点的存储空间
		}
	}
	if (a != NULL)			c->next = a;						//若链表a还有值,则直接填补到末尾
	if (b != NULL)			c->next = b;						//若链表b还有值,则直接填补到末尾	
}
(三)双链表的基本操作
1. 双链表结构体
typedef struct DLNODE
{
	int data;							//存放结点中的数据
	struct DLNODE *prior;				//指向前驱结点的指针
	struct DLNODE* next;				//指向后继结点的指针
}DLNODE;
2. 双链表初始化
/*
method:
	创建双链表
param:
	dlnode	要操作的顺序表
	dat		数组中存放要创建链表的数据
	n		要创建单链表的长度
*/
int Create_DLnode(DLNODE** dlnode, int dat[], int n)
{
	int i = 0;
	DLNODE* p,* q;
	*dlnode = (DLNODE*)malloc(sizeof(DLNODE));				//为dlnode分配内存空间
	(*dlnode)->data = NULL;									//初始化头结点
	(*dlnode)->next = NULL;	
	(*dlnode)->prior = NULL;
	p = (*dlnode);											//p指针指向头结点
	for (int i = 0; i < n; i++)
	{
		q = (DLNODE*)malloc(sizeof(DLNODE));
		q->data = dat[i];
		p->next = q;
		q->prior = p;
		p = q;
	}
	p->next = NULL;											//表尾
	return OK;
}
3. 双链表的查询
/*
method:
	查询双链表数据
param:
	dlnode	要操作的顺序表
	x		要查找的元素值
return
	返回查找到的该结点
*/
DLNODE* Find_DLnode(DLNODE* dlnode, int x)
{
	DLNODE* p;
	p = dlnode->next;										//这里p指针指向第一个结点
	while (p != NULL)										//判断是否循环完链表
	{
		if (p->data == x)									//如果该结点正是所查找数据,直接break,返回该结点
			return p;
		p = p->next;
	}
	return NULL;
	
}
4. 双链表的插入
/*
method:
	向双链表插入数据
param:
	dlnode	要操作的顺序表
	x		要插入的元素值
*/

int Insert_DLnode(DLNODE* dlnode, int x)
{
	DLNODE* p, * q;
	p = dlnode->next;										//p指针指向第一个结点
	q = (DLNODE*)malloc(sizeof(DLNODE));					//创建一个结点,以供插入
	q->data = x;
	q->next = NULL;
	q->prior = NULL;
	while (p != NULL)										//循环链表
	{	
		if (p->data < q->data)								//按照升序进行插入
		{
			if (p->next == NULL)							//如果这里为空,则链表循环完,直接将该结点插入到链表最后方
			{ 
				p->next = q;
				q->prior = p;
				break;
			}
			else
				p = p->next;								//p指向下一个元素
		}
		else
		{													//先假想一下,一链表从中间切开一刀
			q->prior = p->prior;							//先将要插入的结点两端赋值。即:先将q的前驱,后继进行赋值
			q->next = p;
			p->prior = q;									//然后再将被断开的结点的两端进行赋值。即p的前驱,q的前驱的后继
			q->prior->next = q;
			break;
		}
	}
	return OK;
}
5. 双链表的删除
/*
method:
	向双链表删除数据
param:
	dlnode	要操作的顺序表
	x		要删除的元素值
*/

int Delete_DLnode(DLNODE* dlnode, int x)
{
	DLNODE* p;												
	p = dlnode->next;										//p指针指向第一个结点
	while (p != NULL)										//循环链表
	{
		if (p->data == x)									//如果找到要删除的结点
		{													//假象一下,一链表从中间切开一刀,将中间取出一个结点p
			p->next->prior = p->prior;						//然后将断开的两端的链表的前驱和后继进行赋值,这里指的是 p的后继的前驱,
			p->prior->next = p->next;						//和 p的前驱的后继进行赋值
			__vcrt_free_normal(p);
			return OK;
		}
		p = p->next;
	}
	return ERROR;
}
6. 双链表的遍历
/*
method:
		遍历双链表的数据
param:
	dlnode	要操作的顺序表
*/
void Show_DLnode_data(DLNODE* dlnode)
{
	DLNODE* p = dlnode;											//p指向单链表的头结点
	printf("%p", dlnode);										//打印出来头结点指针的地址
	while (p->next != NULL)										//判断下一个结点是否为空
	{
		printf("->%d", p->next->data);							//打印出来链表中的数据
		p = p->next;											//遍历单链表
	}
	printf("\n");
}

发布了46 篇原创文章 · 获赞 75 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/UNIONDONG/article/details/97974884
今日推荐