基本概念
数据元素是数据的基本单位,称为记录。
数据结构有逻辑和存储两种层面的结构;
逻辑结构分为
线性结构:数据元素具有一对一的关系;
树形结构:数据元素具有一对多的关系;
图形结构:数据元素具有多对多的关系;
集合结构:数据元素之间除了同属于一个集合外,没有其他任何的关系;
存储结构分为
顺序结构:数据元素存储在连续分配的地址空间当中;
链式结构:数据元素可以存储在任意合法的地址空间当中,地址空间可以不连续;
索引结构:存储数据元素的同时建立附加的索引表;
散列结构:根据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;
}