LinuxC应用开发学习笔记(四)--数据结构

数据结构

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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值