数据结构和算法

基本概念

数据元素是数据的基本单位,称为记录。
数据结构有逻辑和存储两种层面的结构;
逻辑结构分为
线性结构:数据元素具有一对一的关系;
树形结构:数据元素具有一对多的关系;
图形结构:数据元素具有多对多的关系;
集合结构:数据元素之间除了同属于一个集合外,没有其他任何的关系;
存储结构分为
顺序结构:数据元素存储在连续分配的地址空间当中;
链式结构:数据元素可以存储在任意合法的地址空间当中,地址空间可以不连续;
索引结构:存储数据元素的同时建立附加的索引表;
散列结构:根据key值(哈希)和特定的函数计算出存储位置。

算法

算法是对解决特定问题的步骤的描述。
算法的基本特性有输入,输出,有穷性,确定性,可行性。
算法的设计要求有正确性,可读性,健壮性,时间效率高,存储量低。
衡量算法的指标有
时间复杂度:度量执行算法需要消耗多少时间,即算法执行的基本操作次数;
空间复杂度:度量执行算法需要消耗多少空间,即算法在执行中临时占用的存储空间大小。
通常用大O阶来分析算法的时间复杂度,推导大O阶方法如下:
1、使用常数1替代表达式中的常数项;
2、只保留表达式中最高阶次项;
3、如果最高阶次项存在且不为1,则去掉最高阶次项的系数。
例如 f(n)=3n²+2n+1,其大O阶为O(n²);
常见的时间复杂度有常数阶O(1),线性阶O(n),平方阶O(n2),立方阶O(n3)等,随着算法的输入规模n不断增大,算法执行时间的增长率和算法执行次数的增长率不断增大,即时间复杂度不断增大,则算法的执行效率就越低。

线性表

线性表的数据元素具有线性结构(一对一)

顺序表

顺序表是线性表的顺序存储结构

固定长度

#include <stdio.h>
#include <stdlib.h>
#define SIZE 20

/* 定义顺序表的类型 */
typedef struct list
{
	int data[SIZE];//数据存放的位置
	int last;//标记表中最后一位有效数据的位置
}list_t;

/* 创建表 */
list_t * creat_list()
{
	list_t * list = malloc(sizeof(list_t));//申请空间
	if(list == NULL)//判断实施条件
	{
		printf("空间申请失败!\n");
		return NULL;	
	}

	list->last = -1;//初始化,此时表中没有有效数据

	return list;//返回申请空间的首地址
}

/* 判满 */
int isfull(list_t * list)
{
	return list->last == (SIZE - 1);
}

/* 判空 */
int isnull(list_t * list)
{
	return list->last == -1;
}

/* 增加数据 */
int ins_head_list(list_t * list, int data)
{
	//判断实施条件
	if(isfull(list))
	{
		printf("表为满,无法执行插入操作!\n");
		return -1;
	}

	//挪出位置
	int i;
	for(i = list->last; i >= 0; i--)
	{
		list->data[i+1] = list->data[i];
	}

	//增加数据
	list->data[0] = data;

	//修改last的值
	list->last++;

	return 0;
}

/* 在指定位置增加数据 */
int ins_index_list(list_t * list, int data, int index)
{
	//判断实施条件
	if(isfull(list) || index < 0 || index > list->last+1)
	{
		printf("增加数据,指定位置出错!\n");
		return -1;
	}

	//挪出位置
	int i;
	for(i = list->last; i >= index; i--)
	{
		list->data[i+1] = list->data[i];
	}

	//指定位置存入数据
	list->data[index] = data;

	//修改last的值
	list->last++;

	return 0;
}

/* 删除数据 */
int del_head_list(list_t * list)
{
	//判断实施条件
	if(isnull(list))
	{
		printf("表为空,无法执行删除操作!\n");
		return -1;
	}

	//删除数据
	int i;
	for(i = 0; i < list->last; i++)
	{
		list->data[i] = list->data[i+1];
	}

	//修改last的值
	list->last--;

	return 0;
}

/* 在指定位置删除数据 */
int del_index_list(list_t * list, int index)
{
	//判断实施条件
	if(isnull(list) || index < 0 || index > list->last)
	{
		printf("删除数据,指定位置出错!\n");
		return -1;
	}

	//删除数据
	int i;
	for(i = index; i < list->last; i++)
	{
		list->data[i] = list->data[i+1];
	}

	//修改last的值
	list->last--;

	return 0;
}

/* 打印数据 */
int print_list(list_t * list)
{
	//判断实施条件
	if(isnull(list))
	{
		printf("表为空,无法执行打印操作!\n");
		return -1;
	}

	int i;
	for(i = 0; i <= list->last; i++)
	{
		printf("%d ",list->data[i] );
	}

	printf("\n");

	return 0;
}

/* 修改数据 */
int change_list(list_t * list, int data, int index)
{
	//判断实施条件
	if(isnull(list) || index < 0 || index > list->last)
	{
		printf("修改数据,指定位置出错!\n");
		return -1;	
	}

	//指定位置修改数据
	list->data[index] = data;

	return 0;
}

/* 查找数据 */
int locate_list(list_t * list, int data)
{
	//判断实施条件
	if(isnull(list))
	{
		return -1;
	}

	//遍历表,查找数据,返回位置
	int i;
	for(i = 0; i <= list->last; i++)
	{
		if(list->data[i] == data)
		{
			return i;
		}
	}

	//提示操作者没有找到
	printf("表中没有该数据!\n");
	return -1;
}

/* 清空 */
int clean_list(list_t * list)
{
	list->last = -1;
	return 0;
}

/* 销毁 */
int dis_list(list_t * list)
{
	free(list);
	return 0;
}

int main(int argc, const char *argv[])
{
	list_t * list = creat_list();
	if(list == NULL)
	{
		printf("creat_list执行失败!\n");
		return -1;
	}
	
	int i;
	for(i = 1; i <= 20; i++)
	{
		if(ins_head_list(list, i*10)== 0)
			print_list(list);
	}
	
	for(i = 1; i <= 10; i++)
	{
		if(del_head_list(list) == 0)
			print_list(list);
	}
	
	ins_index_list(list, 666, 6);
	print_list(list);

	del_index_list(list, 6);
	print_list(list);

	change_list(list, 666, 6);
	print_list(list);

	int ret = locate_list(list, 666);
	printf("位置:%d\n", ret);
	
	clean_list(list);
	print_list(list);

	dis_list(list);	
	return 0;
}

可变长度

#include <stdio.h>
#include <stdlib.h>

/* 定义顺序表的类型 */
typedef struct list
{
	int *data;//数据存放的位置
	int size;//顺序表的大小
	int last;//标记表中最后一位有效数据的位置
}list_t;

/* 创建表 */
list_t * creat_list(int size)
{
	list_t * list = malloc(sizeof(list_t));//申请空间
	if(list == NULL)//判断实施条件
	{
		return NULL;	
	}

	//初始化
	list->data = malloc(sizeof(int) * size);
	if(list->data == NULL)
	{
		printf("空间申请失败!\n");
		return NULL;
	}

	list->size = size;

	list->last = -1;//初始化,此时表中没有有效数据

	return list;//返回申请空间的首地址
}

/* 判满 */
int isfull(list_t * list)
{
	return list->last == (list->size - 1);
}

/* 判空 */
int isnull(list_t * list)
{
	return list->last == -1;
}

/* 增加数据 */
int ins_head_list(list_t * list, int data)
{
	//判断实施条件
	if(isfull(list))
	{
		printf("表为满,无法执行插入操作!\n");
		return -1;
	}

	//挪出位置
	int i;
	for(i = list->last; i >= 0; i--)
	{
		list->data[i+1] = list->data[i];
	}

	//增加数据
	list->data[0] = data;

	//修改last的值
	list->last++;

	return 0;
}

/* 在指定位置增加数据 */
int ins_index_list(list_t * list, int data, int index)
{
	//判断实施条件
	if(isfull(list) || index < 0 || index > list->last+1)
	{
		printf("增加数据,指定位置出错!\n");
		return -1;
	}

	//挪出位置
	int i;
	for(i = list->last; i >= index; i--)
	{
		list->data[i+1] = list->data[i];
	}

	//指定位置存入数据
	list->data[index] = data;

	//修改last的值
	list->last++;

	return 0;
}

/* 删除数据 */
int del_head_list(list_t * list)
{
	//判断实施条件
	if(isnull(list))
	{
		printf("表为空,无法执行删除操作!\n");
		return -1;
	}

	//删除数据
	int i;
	for(i = 0; i < list->last; i++)
	{
		list->data[i] = list->data[i+1];
	}

	//修改last的值
	list->last--;

	return 0;
}

/* 在指定位置删除数据 */
int del_index_list(list_t * list, int index)
{
	//判断实施条件
	if(isnull(list) || index < 0 || index > list->last)
	{
		printf("删除数据,指定位置出错!\n");
		return -1;
	}

	//删除数据
	int i;
	for(i = index; i < list->last; i++)
	{
		list->data[i] = list->data[i+1];
	}

	//修改last的值
	list->last--;

	return 0;
}

/* 打印数据 */
int print_list(list_t * list)
{
	//判断实施条件
	if(isnull(list))
	{
		printf("表为空,无法执行打印操作!\n");
		return -1;
	}

	int i;
	for(i = 0; i <= list->last; i++)
	{
		printf("%d ",list->data[i] );
	}

	printf("\n");

	return 0;
}

/* 修改数据 */
int change_list(list_t * list, int data, int index)
{
	//判断实施条件
	if(isnull(list) || index < 0 || index > list->last)
	{
		printf("修改数据,指定位置出错!\n");
		return -1;	
	}

	//指定位置修改数据
	list->data[index] = data;

	return 0;
}

/* 查找数据 */
int locate_list(list_t * list, int data)
{
	//判断实施条件
	if(isnull(list))
	{
		return -1;
	}

	//遍历表,查找数据,返回位置
	int i;
	for(i = 0; i <= list->last; i++)
	{
		if(list->data[i] == data)
		{
			return i;
		}
	}

	//提示操作者没有找到
	printf("表中没有该数据!\n");
	return -1;
}

/* 清空 */
int clean_list(list_t * list)
{
	list->last = -1;
	return 0;
}

/* 销毁 */
int dis_list(list_t * list)
{
	free(list->data);
	free(list);
	return 0;
}

int main(int argc, const char *argv[])
{
	list_t * list = creat_list(20);
	if(list == NULL)
	{
		printf("creat_list执行失败!\n");
		return -1;
	}
	
	int i;
	for(i = 1; i <= 20; i++)
	{
		if(ins_head_list(list, i*10)== 0)
			print_list(list);
	}
	
	for(i = 1; i <= 10; i++)
	{
		if(del_head_list(list) == 0)
			print_list(list);
	}
	
	ins_index_list(list, 666, 6);
	print_list(list);

	del_index_list(list, 6);
	print_list(list);

	change_list(list, 666, 6);
	print_list(list);

	int ret = locate_list(list, 666);
	printf("位置:%d\n", ret);
	
	clean_list(list);
	print_list(list);

	dis_list(list);	
	return 0;
}

链表

链表是线性表的链式存储结构

单向链表

#include <stdio.h>
#include <stdlib.h>

//定义链表的结点类型
typedef struct node
{
	int data;//存储数据
	struct node * next;//指向下一个结点的地址
}link_t;

//创建
link_t * creat_link()
{
	//申请空间
	link_t * head = malloc(sizeof(link_t));
	if(head == NULL)
	{
		printf("空间申请失败!\n");
		return NULL;
	}

	//初始化
	head->next = NULL;

	//返回申请空间的首地址
	return head;
}

//判空
int isnull(link_t * head)
{
	return head->next == NULL;
}

//增加数据
int ins_head_link(link_t * head, int data)
{
	//申请新结点的存储空间
	link_t * newnode = malloc(sizeof(link_t));

	//存入数据
	newnode->data = data;

	//将新结点连入到链表中,顺序不能颠倒
	newnode->next = head->next;
	head->next = newnode;

	return 0;
}

//指定位置增加数据
int ins_index_link(link_t * head, int data, int index)
{
	//位置过小
	if(index < 0 )
	{
		printf("增加数据,指定位置过小!\n");
		return -1;
	}

	//偏移位置
	while(index--)
	{
		head = head->next;
		if(head == NULL)
		{
			printf("增加数据,指定位置过大!\n");
			return -1;
		}
	}

	ins_head_link(head, data);

	return 0;
}

//删除数据
int del_head_link(link_t * head)
{
	//判断实施条件
	if(isnull(head))
	{
		printf("链表为空,无法执行删除操作!\n");
		return -1;
	}

	//标记要删除的结点
	link_t * temp = head->next;

	//删除结点
	head->next = temp->next;

	//释放删除的结点
	free(temp);
	
	return 0;
}

//指定位置删除数据
int del_index_link(link_t * head, int index)
{
	//位置过小
	if(index < 0 || isnull(head))
	{
		printf("删除数据,指定位置过小!\n");
		return -1;
	}

	//偏移位置
	while(index--)
	{
		head = head->next;
		if(head->next == NULL)
		{
			printf("删除数据,指定位置过大!\n");
			return -1;
		}
	}

	del_head_link(head);

	return 0;
}

//打印数据
int print_link(link_t * head)
{
	//判断实施条件
	if(isnull(head))
	{
		printf("链表为空,无法执行打印操作!\n");
		return -1;
	}

	//跳过头结点打印数据
	head = head->next;
	while(head != NULL)
	{
		printf("%d ", head->data);
		head = head->next;
	}

	printf("\n");

	return 0;
}

//修改数据
int change_link(link_t * head, int data, int index)
{
	//位置过小
	if(index < 0 || isnull(head))
	{
		printf("修改数据,指定位置过小!\n");
		return -1;
	}

	//偏移位置
	while(index--)
	{
		head = head->next;
		if(head->next == NULL)
		{
			printf("修改数据,指定位置过大!\n");
			return -1;
		}
	}

	//修改数据
	head->next->data = data;

	return 0;
}

//查找数据
link_t * locate_link(link_t * head, int data)
{
	while(head->next != NULL)
	{
		if(head->next->data == data)
		{
			return head;
		}
		head = head->next;
	}

	printf("表中没有改数据!\n");
	return NULL;
}

//清空
int clean_link(link_t * head)
{
	while(!isnull(head))
	{
		del_head_link(head);
	}

	return 0;
}

//销毁
int dis_link(link_t * head)
{
	clean_link(head);
	free(head);

	return 0;
}

//逆打印1	
int reprint_link(link_t * head)
{
	//创建临时链表
	link_t * temp = creat_link();

	//临时链表从头增加数据
	while(head->next != NULL)
	{
		ins_head_link(temp, head->next->data);
		head = head->next;
	}

	//打印临时链表
	print_link(temp);

	//销毁临时链表
	dis_link(temp);

	return 0;
}

//逆打印2(递归实现)
void reprint1_link(link_t * head)
{
	//递归结束条件
	if(head->next == NULL)
	{
		return ;
	}

	reprint1_link(head->next);

	printf("%d ", head->next->data);

}

//逆序
int reverse_link(link_t * head)
{
	link_t *q, *p;//定义标记头结点后面的有效数据位
	p = head->next;
	head->next = NULL;//头结点的后继置为NULL
	while(p != NULL)//只要数据节点不为空,就将数据位头插到head的后面
	{
		q = p;
		p = p->next;
		
		//头插
		q->next = head->next;
		head->next = q;
	}
	return 0;
}

int main(int argc, const char *argv[])
{
	link_t * link = creat_link();
	if(link == NULL)
	{
		return -1;
	}

	int i;
	for(i = 1; i <= 20; i++)
	{
		ins_head_link(link, i * 10);
	}

	print_link(link);

	for(i = 1; i <= 10; i++)
	{
		del_head_link(link);
	}
	print_link(link);

	ins_index_link(link, 666, 6);
	print_link(link);

	del_index_link(link, 6);
	print_link(link);

	change_link(link, 666, 6);
	print_link(link);

	link_t * ret = locate_link(link, 666);
	del_head_link(ret);
	print_link(link);

	reprint_link(link);
	reprint1_link(link);
	printf("\n");

	reverse_link(link);
	print_link(link);
	
	clean_link(link);
	print_link(link);
	
	dis_link(link);

	return 0;
}

双向链表

#include <stdio.h>
#include <stdlib.h>

//定义双链的结点类型
typedef struct node
{
	int data;//数据域
	struct node * front;//存储前一个结点的地址
	struct node * next;//存储后一个结点的地址
}dblink_t;

//创建双向链表
dblink_t * creat_dblink()
{
	//申请头尾结点的存储空间
	dblink_t * head = malloc(sizeof(dblink_t));
	dblink_t * tail = malloc(sizeof(dblink_t));
	if(head == NULL || tail == NULL)
	{
		printf("空间申请失败!\n");
		return NULL;
	}

	//初始化
	head->next = tail;
	head->front = NULL;
	tail->next = NULL;
	tail->front = head;

	//返回头结点的地址
	return head;
}

//判空
int isnull(dblink_t * head)
{
	return head->next->next == NULL;
}

//从头增加数据
int ins_head_dblink(dblink_t * head, int data)
{
	//申请新结点存储空间
	dblink_t * newnode = malloc(sizeof(dblink_t));

	//存入数据
	newnode->data = data;

	//链接到链表中
	//先修改新结点的前驱和后继
	newnode->next = head->next;
	newnode->front = head;

	//再修改头尾结点的后继和前驱
	head->next = newnode;
	newnode->next->front = newnode;

#if 0
	head->next->front = newnode;
	head->next = newnode;

	newnode->front->next = newnode;
	newnode->next->front = newnode;
#endif
	return 0;
}

//从头删除数据
int del_head_dblink(dblink_t * head)
{
	//判断实施条件
	if(isnull(head))
	{
		printf("表为空,无法执行删除操作!\n");
		return -1;
	}

	//备份删除结点的地址
	dblink_t * temp = head->next;

	//删除数据
	head->next = temp->next;
	temp->next->front = head;

	//释放删除数据的地址
	free(temp);

	return 0;
}

//打印数据
int print_dblink(dblink_t * head)
{
	//判断实施条件
	if(isnull(head))
	{
		return -1;
	}
	//正向打印
	printf("正向打印:");
	while(head->next->next != NULL)
	{
		head = head->next;
		printf("%d ", head->data);
	}
	printf("\n");


	//反向打印
	printf("反向打印:");
	while(head->front != NULL)
	{
		printf("%d ", head->data);
		head = head->front;
	}
	printf("\n");

	return 0;
}

//修改数据
int change_dblink(dblink_t * head, int data, int index)
{
	if(index < 0 || isnull(head))
	{
		return -1;
	}

	while(index--)
	{
		head = head->next;
		if(head->next->next == NULL)
		{
			return -1;
		}
	}

	head->next->data = data;

	return 0;

}

//查找数据
dblink_t *  locate_dblink(dblink_t * head, int data)
{
	while(head->next->next != NULL)
	{
		if(head->next->data == data)
		{
			return head;
		}
		head = head->next;
	}

	printf("表中没有该数据!\n");
	return NULL;
}

//清空
int clean_dblink(dblink_t * head)
{
	while(!isnull(head))
	{
		del_head_dblink(head);
	}
	return 0;
}

//销毁
int dis_dblink(dblink_t * head)
{
	clean_dblink(head);
	free(head->next);//释放尾结点
	free(head);//释放头结点
	return 0;
}

int main(int argc, const char *argv[])
{
	dblink_t * dblink = creat_dblink();
	if(dblink == NULL)
	{
		return -1;
	}
	print_dblink(dblink);

	int i;
	for(i = 1; i <= 20; i++)
	{
		ins_head_dblink(dblink, i * 10);
	}
	print_dblink(dblink);
	
	for(i = 1; i <= 10; i++)
	{
		del_head_dblink(dblink);
	}
	print_dblink(dblink);
	
	change_dblink(dblink , 666, 6);
	print_dblink(dblink);

	dblink_t * ret = locate_dblink(dblink ,666);
	if(ret != NULL)
	{	
		del_head_dblink(ret);
	}
	print_dblink(dblink);

	clean_dblink(dblink);
	dis_dblink(dblink);
	
	return 0;
}

单向循环链表

#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
	int data;
	struct node * next;
}link_t;

//创建
link_t * creat_link()
{
	//申请头结点的空间
	link_t * head = malloc(sizeof(link_t));
	if(head == NULL)
	{
		return NULL;
	}

	//初始化
	head->next = head;

	//返回
	return head;
}

//判空
int isnull(link_t * head)
{
	return head->next == head;
}

//打印
int print_link(link_t * head)
{
	//判空
	if(isnull(head))
	{
		return -1;
	}
	//标记头结点
	link_t * temp = head;
	
	//打印
	head = head->next;
	while(head != temp)
	{
		printf("%d ", head->data);
		head = head->next;
	}

	printf("\n");

	return 0;
}

int main(int argc, const char *argv[])
{
	link_t * link = creat_link();

	return 0;
}

栈是先进后出(FILO)的线性表,即只允许在一端进行数据操作;允许操作(入栈/出栈)的一端称为栈顶;固定的一端称栈底。

顺序栈

顺序栈是栈的顺序存储结构,尾进尾出。

#include <stdio.h>
#include <stdlib.h>

typedef struct 
{
	int *data;//存数据
	int size;//存数据元素个数
	int top;//标记栈顶数据元素的位置
}stack_tt;//栈的数据类型

stack_tt * creat_stack(int size)
{
	stack_tt * stack = malloc(sizeof(stack_tt));
	if(stack == NULL)
	{
		return NULL;
	}
	stack->data = malloc(sizeof(int)*size);
	if(stack->data == NULL)
	{
		return NULL;
	}

	stack->size = size;

	stack->top = -1;

	return stack;
}

//判满
int isfull(stack_tt * stack)
{
	return stack->top == (stack->size - 1);
}

//判空
int isnull(stack_tt * stack)
{
	return stack->top == -1;
}

//增加数据
int push_stack(stack_tt * stack, int data)
{
	if(isfull(stack))
	{
		return -1;
	}
	
	//增加数据
	stack->data[stack->top+1] = data;

	//修改top位置
	stack->top++;

	return 0;
}

//删除数据
int pop_stack(stack_tt * stack, int *data)
{
	//判断实施条件
	if(isnull(stack))
	{
		return -1;
	}
	
	//获取出栈数据
	*data = stack->data[stack->top];

	//删除数据,修改top的位置
	stack->top--;

	return 0;
}

//获取栈顶数据
int get_stack_top(stack_tt * stack, int *data)
{
	//判断实施条件
	if(isnull(stack))
	{
		return -1;
	}

	//获取栈顶数据
	*data = stack->data[stack->top];

	return 0;
}

//打印数据
int print_stack(stack_tt * stack)
{
	//判断实施条件
	if(isnull(stack))
	{
		return -1;
	}

	int i;
	printf("栈顶\n");
	for(i = stack->top; i >= 0; i--)
	{
		printf("%d\n", stack->data[i]);
	}
	printf("栈底\n");

	return 0;
}

//清空
int clean_stack(stack_tt * stack)
{
	stack->top = -1;
	return 0;
}

//销毁
int dis_stack(stack_tt * stack)
{
	free(stack->data);
	free(stack);

	return 0;
}

int main(int argc, const char *argv[])
{
	stack_tt * stack = creat_stack(10);

	int i;
	for( i = 1; i <= 10; i++)
	{
		push_stack(stack, i * 10);
	}
	print_stack(stack);


	int data;
	for(i = 1; i <= 3; i++)
	{
		pop_stack(stack,&data);
		printf("data: %d\n", data);
		print_stack(stack);
	}

	int get_data;
	get_stack_top(stack, &get_data);
	printf("get_data:%d\n", get_data);


	clean_stack(stack);

	dis_stack(stack);

	return 0;
}

链式栈

链式栈是栈的链式存储结构,头进头出。

#include <stdio.h>
#include <stdlib.h>

typedef struct node 
{
	int data ; //存数据
	struct node *next ;//指向下一个结点的地址 
}linkstack_t ;  //链栈的类型

//创建 
linkstack_t *creat_stack(void)
{
	//申请空间
	linkstack_t *head = malloc(sizeof(linkstack_t));

	//判断实施条件
	if(head == NULL)
		return NULL ;

	//初始化
	head->next = NULL ; 

	return head ; 
}

//进栈 
int push_stack(linkstack_t *linkstack , int data)
{
	//申请新结点的空间
	linkstack_t *newnode = malloc(sizeof(linkstack_t));

	//存入数据
	newnode->data = data ; 

	//连入栈中
	newnode->next = linkstack->next ; 
	linkstack->next = newnode ; 

	return 0 ; 
}

//判空 
int isnull(linkstack_t *linkstack)
{
	return linkstack->next == NULL ; 
}

//出栈 
int pop_stack(linkstack_t *linkstack, int *data)
{
	//判断实施条件
	if(isnull(linkstack))
	{
		printf("栈为空, 出栈失败\n");
		return -1 ;
	}

	//标记出栈数据
	linkstack_t *temp = linkstack->next;

	//删除出栈数据
	linkstack->next = temp->next ; 

	//获取出栈数据
	*data = temp->data ; 

	//释放出栈数据
	free(temp);

	return 0 ; 
}

//获取栈顶数据 
int get_top_stack(linkstack_t *linkstack, int *data)
{
	//判断实施条件
	if(isnull(linkstack))
		return -1 ; 

	//获取栈顶数据
	*data = linkstack->next->data ; 

	return 0 ; 
}
//打印数据 
int print_stack(linkstack_t *linkstack)
{
	//判断实施条件
	if(isnull(linkstack))
	{
		printf("栈为空\n");
		return -1 ; 
	}
	
	printf("栈顶\n");
	while(linkstack->next != NULL)
	{
		linkstack = linkstack->next ;
		printf("%d\n", linkstack->data);
	}
	printf("栈底\n");
	return 0 ; 
}

//清空栈 
int clean_stack(linkstack_t *linkstack)
{
	int temp ; 
	while(!isnull(linkstack))
	{
		pop_stack(linkstack, &temp);
	}

	return 0 ; 
}

//销毁栈 
int dis_stack(linkstack_t *linkstack)
{
	clean_stack(linkstack);

	free(linkstack);

	return 0 ;
}
int main(int argc, const char *argv[])
{
	linkstack_t *linkstack = creat_stack() ; 
	if(linkstack == NULL)
	{
		printf("创建失败\n");
		return -1 ; 
	}

	int i ;
	int data ; 
	int data_top ; 
	for(i = 1; i <= 10; i++)
	{
		pust_stack(linkstack, i*10);
	}

	print_stack(linkstack);

	for(i = 1; i <= 3; i++)
	{
		pop_stack(linkstack, &data);
		printf("出栈数据为%d\n",data);
		print_stack(linkstack);
	}

	get_top_stack(linkstack, &data_top);
	printf("此时栈顶数据为%d\n",data_top);
	return 0;
}

队列

队列是先进先出(FIFO)的线性表,允许在两端进行数据操作;数据可以出队的一端称为队头,数据可以入队的一端称为队尾,即尾进头出。

链式队列

链式队列是队列的链式存储结构。

#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
	int data;//存数据
	struct node * next;//保存下一个结点的地址
}node_t;//结点的数据类型

typedef struct queue
{
	node_t * head;//头指针
	node_t * tail;//尾指针
}queue_t;//队列的数据类型


//创建
queue_t * creat_queue()
{
	//申请头结点的数据类型
	node_t * head = malloc(sizeof(node_t));
	if(head == NULL)
	{
		return NULL;
	}

	//初始化
	head->next = NULL;

	//申请头指针和尾指针的存储空间
	queue_t * queue = malloc(sizeof(queue_t));
	if(queue == NULL)
	{
		return NULL;
	}

	//初始化头指针尾指针的指向
	queue->head = head;
	queue->tail = head;

	return queue;//返回标识
}

//判空
int isnull(queue_t * queue)
{
	return queue->head->next == NULL;
//	return queue->head == queue->tail;
}


//入队
int in_queue(queue_t * queue, int data)
{
	//申请新结点的存储空间
	node_t * newnode = malloc(sizeof(node_t));

	//存入数据
	newnode->data = data;

	//入队
	newnode->next = queue->tail->next;
	queue->tail->next = newnode;

	//修改尾指针tail的指向
	queue->tail = newnode;

	return 0;
}

//出队
int out_queue(queue_t * queue, int * data)
{
	//判断实施条件
	if(isnull(queue))
	{
		return -1;
	}

	//备份出队的数据
	node_t * temp = queue->head->next;

	//出队数据
	queue->head->next = temp->next;

	//获取出队数据
	*data = temp->data;

	//释放出队数据
	free(temp);

	//如果出队数据后,队列为空,要找回尾指针的指向
	if(queue->head->next == NULL)
	{
		queue->tail = queue->head;
	}

	return 0;
}

//获取队列的长度
int get_length(queue_t * queue)
{
	//判断实施条件
	if(isnull(queue))
	{
		return 0;
	}

	int len = 0;
	node_t * head = queue->head;
	head = head->next;
	while(head != NULL)
	{
		len++;
		head = head->next;
	}

	return len;
}

//打印数据
int  print_queue(queue_t * queue)
{
	//判空
	if(isnull(queue))
	{
		return -1;
	}

	node_t * head = queue->head;
	head = head->next;
	printf("队头:");
	while(head != NULL)
	{
		printf("%d ", head->data);
		head = head->next;
	}
	printf("队尾\n");

	return 0;
}

//清空
int clean_queue(queue_t * queue)
{
	int temp;
	while(!isnull(queue))
	{
		out_queue(queue, &temp);
	}
	return 0;
}

//销毁
int dis_queue(queue_t * queue)
{
	//清空
	clean_queue(queue);
	//释放
	free(queue->head);
	free(queue);

	return 0;
}

//逆向打印
int reprint_queue(queue_t * queue)
{
	//创建临时栈
	int * stack1 = malloc(sizeof(int) * get_length(queue));
	int top1 = -1;

	int * stack2 = malloc(sizeof(int) * get_length(queue));
	int top2 = -1;
	
	int data;
	//当队列不为空,出队数据,进栈1
	while(!isnull(queue))
	{
		out_queue(queue, &data);
		stack1[++top1] = data;
	}

	//当栈1不为空,出栈1,出来一个打印一个,进栈2
	while(top1 != -1)
	{
		data =	stack1[top1--];
		printf("%d ", data);
		stack2[++top2] = data;
	}
	printf("\n");

	//当栈2不为空,出栈2,进队列
	while(top2 != -1)
	{
		data = stack2[top2--];
		in_queue(queue, data);
	}

	//释放
	free(stack1);
	free(stack2);

	return 0;
}

int main(int argc, const char *argv[])
{
	queue_t * queue = creat_queue();
	if(queue == NULL)
	{
		return -1;
	}

	int i;
	for(i = 1; i <= 10; i++)
	{
		in_queue(queue, i * 10);
	}
	print_queue(queue);

	int out_data;
	for(i = 1; i <= 3; i++)
	{
		out_queue(queue, &out_data);
		printf("out_data:%d\n", out_data);
		print_queue(queue);
	}

	reprint_queue(queue);

	int ret = get_length(queue);
	printf("length:%d\n", ret);

	clean_queue(queue);

	dis_queue(queue);

	return 0;
}

顺序循环队列

顺序循环队列是队列的顺序存储结构。

#include <stdio.h>
#include <stdlib.h>

typedef struct queue
{
	int *data;//存数据
	int size;//标记数据元素个数
	int head;//即将要取数据的位置
	int tail;//即将要存数据的位置
}queue_t;//顺序循环队列的类型

//创建
queue_t * creat_queue(int size)
{
	queue_t * queue = malloc(sizeof(queue_t));
	if(queue == NULL)
	{
		return NULL;
	}

	//初始化
	queue->data = malloc(sizeof(int) * size);
	if(queue->data == NULL)
	{
		return NULL;
	}

	queue->size = size;

	queue->head = 0;
	queue->tail = 0;

	return queue;
}

//判满
int isfull(queue_t * queue)
{
	return  (queue->tail + 1) % queue->size == queue->head ;
}

//判空
int isnull(queue_t * queue)
{
	return queue->head == queue->tail;
}

//入队(尾进)
int in_queue(queue_t * queue, int data)
{
	//判断实施条件
	if(isfull(queue))
	{
		return -1;
	}

	//数据入队
	queue->data[queue->tail] = data;

	//修改tail的值
	queue->tail = (queue->tail+1) % queue->size;
	
	return 0;
}

//出队(头出)
int out_queue(queue_t * queue, int * data)
{
	//判空
	if(isnull(queue))
	{
		return -1;
	}

	//获取出队数据
	*data = queue->data[queue->head];

	//修改head的位置
	queue->head = (queue->head + 1) % queue->size ;

	return 0;
}

//打印数据
int print_queue(queue_t * queue)
{
	//判空
	if(isnull(queue))
	{
		return -1;
	}
	//打印数据
	int i;
	printf("队头:");
	for(i = queue->head; i != queue->tail; i = (i+1)%queue->size)
	{
		printf("%d ", queue->data[i]);
	}
	printf("队尾\n");
	
	return 0;
}

//获取队列长度
int get_length(queue_t * queue)
{
	return (queue->tail + queue->size - queue->head) % queue->size;
}

//清空
int clean_queue(queue_t * queue)
{
	queue->head = 0;
	queue->tail = 0;

	return 0;
}

//销毁
int dis_queue(queue_t * queue)
{
	free(queue->data);
	free(queue);

	return 0;
}

int main(int argc, const char *argv[])
{
	queue_t * queue = creat_queue(10);
	if(queue == NULL)
	{
		return -1;
	}
	
	int i;
	for(i = 1; i <= 9; i++)
	{
		in_queue(queue, i * 10);
	}
	print_queue(queue);

	int out_data;
	for(i = 1; i <= 3; i++)
	{
		out_queue(queue,&out_data );
		printf("out_data:%d\n", out_data);
		print_queue(queue);
	}

	int len = get_length(queue);
	printf("len:%d\n", len);

	clean_queue(queue);

	dis_queue(queue);

	return 0;
}

树的数据元素具有树形结构(一对多),通常是链式存储结构;其遍历方式有
先序遍历(根左右);
中序遍历(左根右);
后序遍历(左右根);
层次遍历(逐层遍历)。

二叉树

#include <stdio.h>
#include <stdlib.h>

typedef struct node
{
	int data;//保存编号
	struct node * lchild;//保存左孩子的地址
	struct node * rchild;//保存右孩子的地址
}tree_t;//树的结点类型

//创建
tree_t * creat_tree(int num)
{
	//结束条件
	if(num  > 6)
	{
		return NULL;
	}

	//申请空间
	tree_t * root = malloc(sizeof(tree_t));

	//初始化编号,左孩子,右孩子
	root->data = num;
	root->lchild = creat_tree(num*2) ;
	root->rchild = creat_tree(num*2 + 1) ;

	return root;
}

//先序遍历(根,左,右)
void pre_tree(tree_t * root)
{
	//结束条件
	if(root == NULL)
	{
		return;
	}
	//遍历自己
	printf("%d ",root->data);

	//遍历左孩子
	pre_tree(root->lchild);

	//遍历右孩子
	pre_tree(root->rchild);
}

//中序遍历(左,根,右)
void mid_tree(tree_t * root)
{
	//结束条件
	if(root == NULL)
	{
		return;
	}

	//遍历左孩子
	mid_tree(root->lchild);

	//遍历自己
	printf("%d ", root->data);

	//遍历右孩子
	mid_tree(root->rchild);
}

//后序遍历(左,右,根)
void post_tree(tree_t * root)
{
	//结束条件
	if(root == NULL)
	{
		return;
	}

	//遍历左孩子
	post_tree(root->lchild);

	//遍历右孩子
	post_tree(root->rchild);

	//遍历自己
	printf("%d ", root->data);
}

//层次遍历
int levev_tree(tree_t * root)
{
	//创建顺序队列
	tree_t * queue[10];
	int head = 0;
	int tail = 0;

	//创建临时变量
	tree_t * temp;

	//入队根节点
	queue[tail++] = root;

	//判断队列不为空
	while(head != tail)
	{
		//出队队头元素
		temp = queue[head++];

		//打印出队数据
		printf("%d ", temp->data);

		//判断有没有左孩子,有入队
		if(temp->lchild != NULL)
		{
			queue[tail++] = temp->lchild;
		}

		//判断有没有右孩子,有入队
		if(temp->rchild != NULL)
		{
			queue[tail++] = temp->rchild;
		}
	}

	printf("\n");
}

int main(int argc, const char *argv[])
{
	tree_t * tree = creat_tree(1);

	printf("先序遍历:");
	pre_tree(tree);
	printf("\n");
	

	printf("中序遍历:");
	mid_tree(tree);
	printf("\n");

	printf("后序遍历:");
	post_tree(tree);
	printf("\n");

	printf("层次遍历:");
	levev_tree(tree);
	
	return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值