数据结构
1、线性表
线性表的头文件
#ifndef SQLIST_H__
#define SQLIST_H__
#define DATASIZE 1024
typedef int datatype;
typedef struct node_st
{
datatype data[DATASIZE];
int last;
/* data */
}sqlist;
/*线性表的创建方式1*/
sqlist *sqlist_create();
/*线性表的创建方式2--二级指针传参*/
void sqlist_creat1(sqlist **);
/*线性表的插入*/
int sqlist_insert(sqlist *,int i,datatype *);
/*线性表的删除*/
int sqlist_delete(sqlist *,int i);
/*线性表的查找*/
int sqlist_find(sqlist *,datatype *);
/*线性表是否为空*/
int sqlist_isempty(sqlist *);
/*线性表设置为空*/
int sqlist_setempty(sqlist *);
/*线性表大小*/
int sqlist_getnum(sqlist *);
/*线性表遍历*/
void sqlist_display(sqlist *);
/*线性表销毁*/
int sqlist_destory(sqlist *);
/*线性表的联合*/
int sqlist_union(sqlist *,sqlist *);
#endif // !SQLIST_H__
线性表的C文件
#include <stdio.h>
#include "sqlist.h"
#include <stdlib.h>
#define DATASIZE 1024
typedef int datatype;
sqlist *sqlist_create()
{
/*创建线性表*/
sqlist *me;
/*分配内存空间*/
me = malloc(sizeof(*me));
/*如果为空,返回空值*/
if (me == NULL)
{
return NULL;
}
/*线性表首位设置为-1*/
me->last = -1;
return me;
}
/*线性表的创建方式2--二级指针传参*/
void sqlist_creat1(sqlist **ptr)
{
/*一级指针分配内存空间*/
*ptr = malloc(sizeof(**ptr));
/*如果为空,返回*/
if (*ptr == NULL)
{
return ;
}
/*线性表首位设置为-1*/
(*ptr)->last =-1;
return ;
}
/**
* @brief 在线性表中插入数据data.
* @param 1、线性表指针入口参数,插入位置,插入数据元素
* @retval int类型的插入状态
*/
int sqlist_insert(sqlist *me,int i,datatype *data)
{
int j;
/*表示线性表已满,没有位置插入*/
if (me->last == DATASIZE-1)
{
return -1;
}
/*表示插入数据位置越界*/
if (i<0 || i>me->last+1)
{
return -2;
}
/*j指向线性表最后一个元素,插入位置小于j,j向前移动*/
for (j = me->last; i <= j; j--)
{
/*数据的后一位等于数据的前一位*/
me->data[j+1] = me->data[j];
}
/*找到空档,插入数据*/
me->data[i] = *data;
/*线性表大小+1*/
me->last++;
return 0;
}
/**
* @brief 线性表的删除
* @param 线性表的指针,删除的位置
* @retval 返回删除状态
*/
int sqlist_delete(sqlist *me,int i)
{
int j;
/*表示删除数据位置越界*/
if (i< 0 || i> me->last)
return -1;
/*数据位置向前覆盖一位,把i位置的数据给覆盖掉,表示元素删除*/
for ( j = i+1; j <= me->last;j++)
me->data[j-1] = me->data[j];
/*线性表的大小-1*/
me->last--;
return 0;
}
/**
* @brief 线性表的查找
* @param 线性表的指针,需要查找的元素
* @retval 返回查找的元素位置
*/
int sqlist_find(sqlist *me,datatype *data)
{
int i;
/*如果线性表为空,那么返回-1*/
if (sqlist_isempty(me) == 0)
return -1;
/*线性表的遍历查找,*/
for (i = 0; i < me->last; i++)
/*直到找到*data*/
if (me->data[i] == *data)
return i;
/*没有查找到,返回-2*/
return -2;
}
/**
* @brief 判断线性表是否为空
* @param 线性表的指针
* @retval 成功返回0,失败返回-1
*/
int sqlist_isempty(sqlist *me)
{
/*如果me->last是-1,表示线性表为空*/
if (me->last == -1)
{
return 0;
}
return -1;
}
/**
* @brief 设置线性表为空
* @param 线性的指针
* @retval 成功返回0
*/
int sqlist_setempty(sqlist *me)
{
/*设置me->last为-1,表示线性表为空*/
me->last = -1;
return 0;
}
/**
* @brief 获取线性表的大小
* @param 线性表指针
* @retval 返回线性表的有多少个元素
*/
int sqlist_getnum(sqlist *me)
{
return (me->last + 1);
}
/**
* @brief 线性表的遍历
* @param 线性表指针
* @retval 返回线性表的有多少个元素
*/
void sqlist_display(sqlist *me)
{
int i;
/*如果线性表的为空,返回空值*/
if (me->last == -1)
return;
/*遍历线性表*/
for ( i = 0; i <= me->last; i++)
{
printf("%d ",me->data[i]);
}
/*打印换行符*/
printf("\n");
return;
}
/**
* @brief 线性表的销毁
* @param 线性表指针
* @retval 返回0表示销毁成功
*/
int sqlist_destory(sqlist *me)
{
/*释放线性表*/
free(me);
return 0;
}
/**
* @brief 线性表的联合
* @param 线性表指针1,指针2
* @retval 返回0表示销毁成功
*/
int sqlist_union(sqlist *list1,sqlist *list2)
{
// list 1-> 12 23 34 45 56
// list 2-> 78 89 56 23 10
int i;
for(i=0;i <= list2->last;i++)
{
/*如果线性表2的数据没有在线性表1中找到*/
if (sqlist_find(list1,&list2->data[i])<0)
{
/*将线性表2的数据插入到线性表1的0位置*/
sqlist_insert(list1,0,&list2->data[i]);
}
}
}
线性表的main.c文件
#include <stdio.h>
#include "sqlist.h"
#include <stdlib.h>
int main()
{
/*创建2个线性表的指针*/
sqlist *list = NULL;
sqlist *list1 = NULL;
/*初始化2个数组*/
datatype arr[] = {12,23,34,45,56};
datatype arr1[] = {89,98,67,47,53};
int i;
int err;
/*创建线性表*/
list = sqlist_create();
// sqlist_creat1(&list);
/*错误判断语句,如果为空,则返回错误*/
if(list == NULL)
{
fprintf(stderr,"sqlist_creat() failed!\n");
exit(1);
}
/*创建线性表1*/
list1 = sqlist_create();
/*错误判断语句,如果为空,则返回错误*/
if (list1 == NULL)
{
fprintf(stderr,"sqlist1_creat() failed!\n");
exit(1);
}
/*测试语句*/
// printf("%d %d\n",__LINE__,sizeof(arr)/sizeof(*arr));
/*初始化线性表*/
for ( i = 0; i < sizeof(arr)/sizeof(*arr); i++)
{
/*判断插入失败的错误类型*/
if((err = sqlist_insert(list,0,&arr[i]))!=0)
{
/*线性表已满*/
if(err == -1)
fprintf(stderr,"The arr is full.\n");
/*插入位置错误*/
else if (err == -2)
fprintf(stderr,"The position you wan to insert is wrong.\n");
/*其他错误*/
else
fprintf(stderr,"error!");
exit(1);
}
}
/*线性表的遍历*/
sqlist_display(list);
/*初始化线性表1*/
for (int i = 0; i < sizeof(arr1)/sizeof(*arr1); i++)
{
sqlist_insert(list1,0,&arr1[i]);
}
/*线性表1的遍历*/
sqlist_display(list1);
/*删除线性表的第一个元素*/
sqlist_delete(list,1);
// printf("%d\n",ret);
/*再次遍历线性表*/
sqlist_display(list);
#if 0
/*线性表的联合*/
sqlist_union(list,list1);
/*查看联合结果*/
sqlist_display(list);
/*销毁线性表*/
sqlist_destory(list1);
#endif
exit(0);
}
2、 有头结点的单向链表
单向链表的.h文件
#ifndef LIST_H__
#define LIST_H__
typedef int datatype;
typedef struct node_st
{
datatype data;
struct node_st *next;
}list;
/*链表的创建*/
list* list_create();
/*链表按位置插入*/
int list_insert_at(list *,int i,datatype *);
/*链表按顺序插入*/
int list_order_insert(list *,datatype *);
/*链表按位置删除*/
int list_delete_at(list*,int i,datatype *);
/*链表的删除*/
int list_delete(list *,datatype *);
/*判断链表是否为空*/
int list_isempty(list *);
/*链表的遍历*/
void list_display(list*);
/*链表的销毁*/
void list_destory(list *);
#endif // !LIST_H__#define ""
单向链表的.c文件
#include <stdio.h>
#include <stdlib.h>
#include "linklist.h"
/**
* @brief 链表的创建
* @param 无
* @retval 返回创建成功的链表首地址
*/
list* list_creat()
{
/*创建一个带头节点的单链表*/
list *me;
/*分配内存空间*/
me = malloc(sizeof(*me));
if (me == NULL)
return NULL;
/*数据域不管,指针域设置为空指针*/
me->next = NULL;
return me;
}
/**
* @brief 链表的位置插入
* @param 链表名称,插入位置,插入数据
* @retval 返回0表示插入成功
*/
int list_insert_at(list *me,int i,datatype *data)
{
int j = 0;
/*创建一个链表,存放me*/
list *node = me,*newnode;
/*如果插入位置小于0,返回错误*/
if (i<0)return -1;
/*node指针一个个向后找,直到找到了某一个节点*/
while (j<i&& node != NULL)
{
node = node->next;
j++;
}
/*如果node指针不为空,表示找到一个有效位置作为插入,获得的是待插入位置的前驱节点*/
/*单向链表只能单向移动,找不到后继节点的前驱指针*/
if (node)
{
newnode = malloc(sizeof(*newnode));
if (newnode == NULL)
return -2;
/*使用新的newnode存放需要插入的数据*/
newnode->data = *data;
/*首先设置指针为空*/
newnode->next = NULL;
/*新节点的next指针等于旧节点的next指针(旧节点的后继节点)*/
newnode->next = node->next;
/*旧节点的next指向新节点的本身*/
node->next = newnode;
return 0;
}
/*表示第i个位置是不合法的*/
else
return -3;
}
/**
* @brief 链表的遍历
* @param 链表指针
* @retval 返回为空
*/
void list_display(list*me)
{
list *node = me->next;
/*如果链表为空,返回*/
if(list_isempty(me) == 0)
{
return;
}
/*链表不为空,打印链表数据*/
while (node!=NULL)
{
printf("%d ",node->data);
node = node->next;
}
printf("\n");
return ;
}
/**
* @brief 链表的顺序插入
* @param 链表指针,待插入数据
* @retval 返回插入状态
*/
int list_order_insert(list *me,datatype *data)
{
list *p = me,*q;
/*p插入节点的前驱位置*/
while (p->next && p->next->data<*data)
/*继续向后移动*/
p = p->next;
/*申请内存空间*/
q = malloc(sizeof(*q));
if (q == NULL)
return -1;
/*存放数据*/
q->data = *data;
/*插入数据*/
q->next = p->next;
/*插入成功*/
p->next = q;
return 0;
}
/**
* @brief 链表的位置删除
* @param 链表指针,待删除位置,待删除数据
* @retval 返回删除状态
*/
int list_delete_at(list*me,int i,datatype *data)
{
int j = 0;
list *p = me,*q;
/*初始化设置数据为-1,观察返回值的状态*/
*data = -1;
/*删除位置错误*/
if (i<0)
{
return -1;
}
/*当j<i,并且p不为空,一直向后找*/
while (j<i&&p)
{
p = p->next;
j++;
}
/*当指针p不为空,表示找到了*/
if (p)
{
/* q指向p的后继节点 */
q = p->next;
/* p的后继节点指向q的后继节点 */
p->next = q->next;
*data = q->data;
/*释放指针q*/
free(q);
q = NULL;
return 0;
}
/*表示没有找到*/
else
{
return -2;
}
}
/**
* @brief 链表的数据删除
* @param 链表指针,待删除数据
* @retval 返回删除状态
*/
int list_delete(list *me,datatype *data)
{
list *p = me,*q;
/*一直寻找需要删除的数据,知道找到为止*/
while (p->next && p->next->data != *data)
{
p=p->next;
}
if (p->next == NULL )
return -1;
else
{
/*保存p的后继节点*/
q = p->next;
/*p的后继节点保存q的后继节点*/
p->next = q->next;
/*释放q*/
free(q);
q = NULL;
}
}
/**
* @brief 判断链表释放为空
* @param 链表指针
* @retval 返回删除状态,0为空,1非空
*/
int list_isempty(list *me)
{
if (me->next == NULL)
return 0;
return 1;
}
/**
* @brief 链表的销毁
* @param 链表指针
* @retval 空
*/
void list_destory(list *me)
{
list *node,*next;
/* node 指向 me的后继节点,逐个释放node */
for(node = me->next;node!=NULL;node = next)
{
next = node->next;
free(node);
}
free(me);
return;
}
单向链表表的main.c文件
#include <stdio.h>
#include <stdlib.h>
#include "linklist.h"
int main()
{
/*链表的创建*/
list *l;
int i,err;
datatype arr[] = {12,9,23,2,34,6,45};
l = list_creat();
if (l == NULL)
{
exit(1);
}
/*链表的初始化*/
for (i = 0; i < sizeof(arr)/sizeof(*arr); i++)
{
if(list_order_insert(l,&arr[i]))
//if(list_insert_at(l,0,&arr[i]))
exit(1);
}
/*链表的遍历*/
list_display(l);
datatype value;
/*链表按照位置删除测试*/
err = list_delete_at(l,2,&value);
if (err)
{
exit(1);
}
list_display(l);
/*打印链表删除数据*/
printf("delete:%d\n",value);
#if 0
int value = 12;
list_delete(l,&value);
list_display(l);
#endif
list_destory(l);
exit(0);
}
3、无头结点的单向链表
无头结点的单向链表.h文件
#ifndef NOHEAD_H__
#define NOHEAD_H__
#define NAMESIZE 32
struct score_st
{
int id;
char name[NAMESIZE];
int math;
int chinese;
};
struct node_st
{
struct score_st data;
struct node_st *next;
};
/*链表插入*/
int list_insert(struct node_st **,struct score_st *);
/*链表显示*/
void list_show(struct node_st *);
/*链表删除*/
int list_delete(struct node_st **);
/*链表查找*/
struct score_st * list_find(struct node_st*,int id);
/*链表销毁*/
void list_destory(struct node_st* );
#endif
无头结点的单向链表.c文件
#include <stdio.h>
#include <stdlib.h>
#include "noheadlink.h"
/**
* @brief 链表插入
* @param 待插入数据
* @retval 插入状态
*/
/*二级指针传参*/
int list_insert(struct node_st **list,struct score_st *data)
{
struct node_st *new;
/* 开辟内存空间并且判断*/
new = malloc(sizeof(*new));
if (new == NULL)
return -1;
/*新节点的数据保存*/
new->data = *data;
new->next = NULL;
/*找到并且保存list的指针*/
new->next = *list;
/* list 就是新节点 */
*list = new;
return 0;
}
/**
* @brief 链表显示
* @param 链表指针
* @retval 空
*/
void list_show(struct node_st *list)
{
struct node_st *cur;
for (cur = list;cur != NULL;cur=cur->next)
{
printf("%d %s %d %d \n",cur->data.id,cur->data.name,cur->data.math,cur->data.chinese);
}
}
/**
* @brief 链表删除第一个有效节点
* @param 链表指针
* @retval 删除状态
*/
int list_delete(struct node_st **list)
{
struct node_st *cur;
if (*list == NULL)
return -1;
/*保存当前节点*/
cur = *list;
/*当前节点指向下一个节点*/
*list = (*list)->next;
free(cur);
return 0;
}
/**
* @brief 链表查找
* @param 链表,位置
* @retval 链表指针
*/
struct score_st *list_find(struct node_st*list,int id)
{
struct node_st *cur;
/*循环查找,查看是否找到*/
for (cur = list; cur != NULL;cur = cur->next)
{
/*如果找到id*/
if(cur->data.id == id)
return &cur->data;
}
/*没有找到id,返回NULL*/
return NULL;
}
/**
* @brief 链表销毁
* @param 链表指针
* @retval 无
*/
void list_destory(struct node_st* list)
{
struct node_st *cur;
if (list == NULL)
return;
/*逐个释放*/
for (cur = list;cur!= NULL;cur = list)
{
list = cur->next;
free(cur);
}
}
无头结点的main.c文件
#include <stdio.h>
#include <stdlib.h>
#include "noheadlink.h"
int main()
{
struct node_st *list = NULL;
struct score_st tmp;
int i,ret;
/*初始化无头链表*/
for ( i = 0; i < 7; i++)
{
tmp.id = i;
snprintf(tmp.name,NAMESIZE,"std %d",i);
tmp.math = rand()%100;
tmp.chinese = rand()%100;
ret = list_insert(&list,&tmp);
if (ret != 0)
exit(1);
}
/*链表显示*/
list_show(list);
printf("\n\n");
// list_delete(&list);
// list_show(list);
int id = 13;
struct score_st *ptr;
/*链表查找测试*/
ptr = list_find(list,id);
if(ptr == NULL)
printf("can't find\n");
else
printf("%d %s %d %d \n",ptr->id,ptr->name,ptr->math,(*ptr).chinese);
/*链表销毁*/
list_destory(list);
exit(0);
}
4、多项式合并的文件—有头链表的实现
#include <stdio.h>
#include <stdlib.h>
struct node_st
{
int coef;//系数
int exp;//指数
struct node_st *next;
};
/*多项式的创建,返回值是链表的起始位置*/
struct node_st *ploy_create(int a[][2],int n)
{
struct node_st *me;
struct node_st *newnode,*cur;
int i;
/*创建最简模型*/
me = malloc(sizeof(*me));
if (me == NULL)
exit(1);
me->next = NULL;
/*保存当前结点,cur代替me向后移动,me一直指向第一个结点*/
cur = me;
for (i = 0;i<n;i++)
{
newnode = malloc(sizeof(*newnode));
if(newnode == NULL)
return NULL;
newnode->coef = a[i][0];
newnode->exp = a[i][1];
newnode->next = NULL;
/*新结点连接完成*/
cur->next = newnode;
cur = newnode;
}
return me;
}
/*多项式的遍历*/
void poly_show(struct node_st *me)
{
struct node_st *cur;
for (cur = me->next;cur!=NULL;cur = cur->next)
{
printf("(%d %d) ",cur->coef,cur->exp);
}
printf("\n");
}
/*多项式的合并*/
void poly_union(struct node_st *p1,struct node_st *p2)
{
struct node_st *p,*q,*r;
p = p1->next;
q = p2->next;
r = p1;
while (p && q)
{
/* p的指数小于q的指数,那么把p连进来*/
if (p->exp<q->exp)
{
/*把p连进来*/
r->next = p;
/* r指向当前链表的有效的结点 */
r = p;
/* p指向下一个结点 */
p = p->next;
}
/* p的指数大于q的指数,那么把q连进来*/
else if (p->exp>q->exp)
{
/*把q连进来*/
r->next = q;
/* r指向当前链表的有效的结点 */
r = q;
/* q指向下一个结点 */
q = q->next;
}
/* p的指数等于q的指数,合并并且判断系数是否为0*/
else
{
/*系数相加*/
p->coef += q->coef;
/*如果系数累加之后为0*/
if (p->coef)
{
/* r的下一结点指向p */
r->next = p;
/* r移动到p的位置 */
r = p;
}
/*如果系数累加之后不为0*/
p = p->next;
q = q->next;
}
}
if (p == NULL)
r->next = q;
else
r->next = p;
}
int main()
{
int a[][2] = {{5,0},{2,1},{8,8},{3,16}};
int b[][2] = {{6,1},{16,6},{-8,8}};
struct node_st *p1,*p2;
p1 = ploy_create(a,4);
if (p1 == NULL)
{
exit(1);
}
p2 = ploy_create(b,3);
if (p2 == NULL)
{
exit(1);
}
poly_show(p1);
poly_show(p2);
poly_union(p1,p2);
poly_show(p1);
}
5、约瑟夫环问题----循环链表
约瑟夫环的单向环链文件
//单项环链
#include <stdio.h>
#include <stdlib.h>
#define JOSE_NR 8
struct node_st
{
int data;
struct node_st *next;
};
/*约瑟夫环的创建*/
struct node_st *jose_create(int n)
{
struct node_st *me;
int i = 1;
struct node_st *newnode,*cur;
me = malloc(sizeof(*me));
if (me == NULL)
return NULL;
/*me链表的初始化,初始化的值为i*/
me->data = i;
/*me的next的指针指向me自身*/
me->next = me;
i++;
/*以上完成只有一个节点的单向循环链表*/
/*存放当前的节点,保证me不变*/
cur = me;
/*初始化约瑟夫环*/
for (;i<=n;i++)
{
/*创建新的结点往后继续添加*/
newnode = malloc(sizeof(*newnode));
if(newnode == NULL)
return NULL;
newnode->data = i;
/*新结点的next咬住头*/
newnode->next = me;
/*相当于me继续向下指向*/
cur->next = newnode;
/*给cur重新赋值*/
cur = newnode;
}
/*返回起始位置*/
return me;
}
/*约瑟夫环的遍历*/
void jose_show(struct node_st *me)
{
struct node_st *list;
/*list的下一个结点不等于头结点*/
for (list = me;list->next!=me;list = list->next)
{
printf("%d ",list->data);
}
/*打印最后一个有效记录*/
printf("%d\n",list->data);
}
/*约瑟夫环的销毁*/
void jose_kill( struct node_st **me,int n)
{
struct node_st *cur = *me,*node;
int i = 1;
/*当还有结点的时候,继续向下移动*/
while(cur != cur->next)
{
while (i<n)
{
/*node和cur指向同一个位置*/
node = cur;
/*向后移动*/
cur = cur->next;
i++;
}
/*打印删除的数据*/
printf("%d ",cur->data);
/*跳过了cur结点*/
node->next = cur->next;
free(cur);
/*给cur重新赋值*/
cur = node->next;
/*i从1继续数数*/
i = 1;
}
/*cur指向7,cur的尾巴也指向cur自己*/
*me = cur;
printf("\n");
}
int main()
{
struct node_st *list;
int n = 3;
/*约瑟夫环的创建*/
list = jose_create(JOSE_NR);
if (list == NULL)
exit(1);
jose_show(list);
/*传递二级指针*/
jose_kill(&list,3);
jose_show(list);
exit(0);
}