C语言数据结构之顺序结构(Sequence)

C语言数据结构之顺序结构(Sequence)

简单的顺序结构,通常称之为序列

  • 定义数据结构struct Sequence,用数组来保存数据!!!
  • 结构体成员int *elts,其实是整数数组,只保存整数数据,也只能测试整数!!!
  • 实现基本功能,创建、释放、追加、插入、删除、更改、查找、判断、逐项操作等功能
  • sequence_new 创建
  • sequence_free 释放
  • sequence_is_empty 是否为空
  • sequence_is_full 是否已满
  • sequence_append 追加数据
  • sequence_insert 插入数据
  • sequence_remove 删除数据
  • sequence_set 更改数据
  • sequence_get 获取数据
  • sequence_reverse 倒置序列
  • sequence_foreach 对序列进行逐项操作
  • 我在每个函数前面加了一个mg_做为自己的命名空间标识,namespace很重要!!!
  • C++中的封装,在C语言中基本可以完成,只要实现了上述功能!!!

代码如下:

/* filename: seq.c */
#include <stdio.h>
#include <stdlib.h>

/* compile : gcc seq.c -o seq
       run : ./seq              */

/**/
#define SSIZE 32

/* function pointer with int arg and without return */
typedef void (*MgFunc) (int val);

/* define Sequence datatype */
typedef struct _Sequence Sequence;
struct _Sequence {
  int *elts;   //elements
  int size;    //size
  int maxsize; //maxsize
};

/* create a new sequence */
Sequence *
mg_sequence_new (void)
{
  Sequence *seq = (Sequence*) malloc (sizeof(Sequence));
  seq->size = 0; seq->maxsize = SSIZE;
  seq->elts = (int*) malloc (seq->maxsize * sizeof(int));
  return seq;
}

/* free the sequence */
void
mg_sequence_free (Sequence *seq)
{
  free (seq->elts);
  free (seq);
}

/* sequence is empty return 1 else return 0 */
int
mg_sequence_is_empty (Sequence *seq)
{
  if (seq->size == 0) return 1;
  return 0;
}

/* sequence is full return 1 else return 0 */
int
mg_sequence_is_full (Sequence *seq)
{
  if (seq->size == seq->maxsize) return 1;
  return 0;
}

/* append a val into sequence */
void
mg_sequence_append (Sequence *seq, int val)
{
  seq->elts[seq->size] = val;
  seq->size = seq->size + 1;
  if (seq->size >= seq->maxsize)
    printf ("Warnning: Sequence is full!\n");
}

/* insert a val at idx into sequence */
void
mg_sequence_insert (Sequence *seq, int idx, int val)
{
  for (int i = seq->size - 1; i >= idx; i--)
    seq->elts[i+1] = seq->elts[i];
  seq->elts[idx] = val;
  seq->size = seq->size + 1;
}

/* set a val at idx of sequence */
void
mg_sequence_set (Sequence *seq, int idx, int val)
{
  seq->elts[idx] = val;
}

/* remove a val at idx of sequence */
void
mg_sequence_remove (Sequence *seq, int idx)
{
  for (int i = idx; i <= seq->size; i++)
    seq->elts[i] = seq->elts[i+1];
  seq->size = seq->size - 1;
}

/* get a val at idx of sequence */
int
mg_sequence_get (Sequence *seq, int idx)
{
  return seq->elts[idx];
}

/* reverse the sequence */
void
mg_sequence_reverse (Sequence *seq)
{
  for (int i = 0, j = seq->size - 1; i < seq->size / 2; i++, j--)
    {
      int tmp = seq->elts[i];
      seq->elts[i] = seq->elts[j];
      seq->elts[j] = tmp;
    }
}

/* call mgfunc on each element */
void
mg_sequence_foreach (Sequence *seq, MgFunc mgfunc)
{
  for (int i = 0; i < seq->size; i++)
    mgfunc (seq->elts[i]);
}

/* ---------------------------------------- */

/* define function for MgFunc */
void
out_integer (int val)
{
  printf ("%d ", val);
}

/**/
int
main (int argc, char *argv[])
{
  Sequence *seq = mg_sequence_new ();

  for (int i = 0; i < 10; i++)
    mg_sequence_append (seq, i + 1000);

  printf ("Test sequence new, append, foreach method:\n");
  mg_sequence_foreach (seq, out_integer);

  printf ("\nTest sequence insert method:\n");
  mg_sequence_insert (seq, 5, 8888);
  mg_sequence_foreach (seq, out_integer);

  printf ("\nTest sequence reverse method:\n");
  mg_sequence_reverse (seq);
  mg_sequence_foreach (seq, out_integer);

  printf ("\nTest sequece remove method:\n");
  mg_sequence_remove (seq, 5);
  mg_sequence_foreach (seq, out_integer);
  printf ("\n");

  mg_sequence_free (seq);
  return 0;
}
/* -----(:/.^.\:)-----*/

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc seq.c -o seq
songvm@ubuntu:~/works/xdn/soo$ ./seq
Test sequence new, append, foreach method:
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 
Test sequence insert method:
1000 1001 1002 1003 1004 8888 1005 1006 1007 1008 1009 
Test sequence reverse method:
1009 1008 1007 1006 1005 8888 1004 1003 1002 1001 1000 
Test sequece remove method:
1009 1008 1007 1006 1005 1004 1003 1002 1001 1000 
  • 基本完成了上述功能,并通过测试!!!
  • 注意:没有对出错情况做限制!!!

将功能扩展一下,让序列可以保存更多的数据类型

  • 上面的序列只能保存整型数据,完全可以将其改造成保存多种类型数据,就是用void*替换原来的int!!!
  • 因为void*和long的sizeof值都是8字节,所以既可以保存指针类型数据也可以保存长整型数据!!!
  • 而double的sizeof值也是8字节,所以还可以保存浮点型数据!!!
  • C++中的多态就是这么做的吧?!?
  • 不在限制数组的长度,理论上可以无限制分配内存,事实上要根据使用场合来做出限制!!!

代码如下:

/* filename: seqv.c */
#include <stdio.h>
#include <stdlib.h>

/* compile : gcc seqv.c -o seqv
       run : ./seqv              */

/**/
#define SPSIZE 8

/* function pointer with void* arg and without return */
typedef void (*MgFunc) (void *val);

/* define Sequence datatype */
typedef struct _Sequence Sequence;
struct _Sequence {
  int size;     //size
  int ps;       //page size
  void **elts;  //elements
};

/* create a new sequence */
Sequence *
mg_sequence_new (void)
{
  Sequence *seq = (Sequence*) malloc (sizeof(Sequence));
  seq->size = 0; seq->ps = 1;
  seq->elts = (void**) malloc (seq->ps * SPSIZE * sizeof(void*));
  for (int i = 0; i < SPSIZE; i++)
    seq->elts[i] = NULL;
  return seq;
}

/* free every elements */
void
mg_sequence_free_elements (Sequence *seq)
{
  for (int i = 0; i < seq->size; i++)
    free (seq->elts[i]);
}

/* free the sequence */
void
mg_sequence_free (Sequence *seq)
{
  free (seq->elts);
  free (seq);
}

/* sequence is empty return 1 else return 0 */
int
mg_sequence_is_empty (Sequence *seq)
{
  if (seq->size == 0) return 1;
  return 0;
}

/* sequence is full return 1 else return 0 */
/*int
mg_sequence_is_full (Sequence *seq)
{
  if (seq->size == seq->maxsize) return 1;
  return 0;
}
*/

/* */
int
mg_sequence_size (Sequence *seq)
{
  return seq->size;
}

/* append a val into sequence */
void
mg_sequence_append (Sequence *seq, void *val)
{
  seq->elts[seq->size] = val;
  seq->size = seq->size + 1;
  if (seq->size == seq->ps * SPSIZE)
    {
      seq->ps = seq->ps + 1;
      seq->elts = realloc (seq->elts, seq->ps * SPSIZE * sizeof(void*));
    }
}

/* insert a val at idx into sequence */
void
mg_sequence_insert (Sequence *seq, int idx, void *val)
{
  for (int i = seq->size - 1; i >= idx; i--)
    seq->elts[i+1] = seq->elts[i];
  seq->elts[idx] = val;
  seq->size = seq->size + 1;
}

/* set a val at idx of sequence */
void
mg_sequence_set (Sequence *seq, int idx, void *val)
{
  seq->elts[idx] = val;
}

/* remove a val at idx of sequence */
void
mg_sequence_remove (Sequence *seq, int idx)
{
  for (int i = idx; i <= seq->size; i++)
    seq->elts[i] = seq->elts[i+1];
  seq->size = seq->size - 1;
}

/* get a val at idx of sequence */
void *
mg_sequence_get (Sequence *seq, int idx)
{
  return seq->elts[idx];
}

/* reverse the sequence */
void
mg_sequence_reverse (Sequence *seq)
{
  for (int i = 0, j = seq->size - 1; i < seq->size / 2; i++, j--)
    {
      void *tmp = seq->elts[i];
      seq->elts[i] = seq->elts[j];
      seq->elts[j] = tmp;
    }
}

/* call mgfunc on each element */
void
mg_sequence_foreach (Sequence *seq, MgFunc mgfunc)
{
  for (int i = 0; i < seq->size; i++)
    mgfunc (seq->elts[i]);
}

/* ---------------------------------------- */

/* define function for MgFunc */
void
out_longint (void *val)
{
  printf ("%ld ", (long)(val));
}

/**/
void
test_sequence_longint (void)
{
  Sequence *seq = mg_sequence_new ();

  for (long i = 0; i < 10; i++)
    mg_sequence_append (seq, (void*)(i + 1000));

  printf ("Test sequence new, append, foreach method:\n");
  mg_sequence_foreach (seq, out_longint);

  printf ("\nTest sequence insert method:\n");
  mg_sequence_insert (seq, 5, (void*)(8888));
  mg_sequence_foreach (seq, out_longint);

  printf ("\nTest sequence reverse method:\n");
  mg_sequence_reverse (seq);
  mg_sequence_foreach (seq, out_longint);

  printf ("\nTest sequence remove method:\n");
  mg_sequence_remove (seq, 5);
  mg_sequence_foreach (seq, out_longint);

  printf ("\nSequence page size : %d\n", SPSIZE);
  printf ("Sequence size : %d\n", seq->size);
  printf ("Sequence page : %d\n", seq->ps);

  printf ("Sequence val at index 9 is %ld\n", (long)mg_sequence_get(seq, 9));

  mg_sequence_free (seq);
}

/*
void
out_string (void *val)
{
  printf ("%s ", (char*)val);
}

//
void
test_sequence_string (void)
{
  char *buff[6] = {"Not", "Only", "Test", "Here", "Another", "Behind"};
  Sequence *seq = mg_sequence_new ();
  for (int i = 0; i < 6; i++)
    mg_sequence_append (seq, buff[i]);
  mg_sequence_foreach(seq, out_string);
  printf ("\n");
  mg_sequence_free (seq);
}

//
void
test_sequence_string_malloc (void)
{
  Sequence *seq = mg_sequence_new ();

  for (int i = 1000; i < 1010; i++)
    {
      char *buf = (char*) malloc (16);
      sprintf (buf, "demo-%d", i);
      mg_sequence_append (seq, buf);
    }

  mg_sequence_foreach(seq, out_string);
  printf ("\n");

  mg_sequence_free_elements (seq);
  mg_sequence_free (seq);
}
*/

/**/
int
main (int argc, char *argv[])
{
  test_sequence_longint ();
  //test_sequence_string ();
  //test_sequence_string_malloc ();
  return 0;
}
/* -----(:/.^.\:)-----*/

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc seqv.c -o seqv
songvm@ubuntu:~/works/xdn/soo$ ./seqv
Test sequence new, append, foreach method:
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 
Test sequence insert method:
1000 1001 1002 1003 1004 8888 1005 1006 1007 1008 1009 
Test sequence reverse method:
1009 1008 1007 1006 1005 8888 1004 1003 1002 1001 1000 
Test sequence remove method:
1009 1008 1007 1006 1005 1004 1003 1002 1001 1000 
Sequence page size : 8
Sequence size : 10
Sequence page : 2
Sequence val at index 9 is 1000
songvm@ubuntu:~/works/xdn/soo$ 

再测试一下序列中保存字符串

  • 将上面代码中的注释去掉
  • sprintf 函数,用printf格式将内容输出到字符串中

代码如下:

/* filename: seqv.c */
#include <stdio.h>
#include <stdlib.h>

/* compile : gcc seqv.c -o seqv
       run : ./seqv              */

/* Sequence page size */
#define SPSIZE 8

/* function pointer with void* arg and without return */
typedef void (*MgFunc) (void *val);

/* define Sequence datatype */
typedef struct _Sequence Sequence;
struct _Sequence {
  int size;     //size
  int ps;       //page size
  void **elts;  //elements
};

/* create a new sequence */
Sequence *
mg_sequence_new (void)
{
  Sequence *seq = (Sequence*) malloc (sizeof(Sequence));
  seq->size = 0; seq->ps = 1;
  seq->elts = (void**) malloc (seq->ps * SPSIZE * sizeof(void*));
  for (int i = 0; i < SPSIZE; i++)
    seq->elts[i] = NULL;
  return seq;
}

/* free every elements */
void
mg_sequence_free_elements (Sequence *seq)
{
  for (int i = 0; i < seq->size; i++)
    free (seq->elts[i]);
}

/* free the sequence */
void
mg_sequence_free (Sequence *seq)
{
  free (seq->elts);
  free (seq);
}

/* sequence is empty return 1 else return 0 */
int
mg_sequence_is_empty (Sequence *seq)
{
  if (seq->size == 0) return 1;
  return 0;
}

/* sequence is full return 1 else return 0 */
/*int
mg_sequence_is_full (Sequence *seq)
{
  if (seq->size == seq->maxsize) return 1;
  return 0;
}
*/

/* */
int
mg_sequence_size (Sequence *seq)
{
  return seq->size;
}

/* append a val into sequence */
void
mg_sequence_append (Sequence *seq, void *val)
{
  seq->elts[seq->size] = val;
  seq->size = seq->size + 1;
  if (seq->size == seq->ps * SPSIZE)
    {
      seq->ps = seq->ps + 1;
      seq->elts = realloc (seq->elts, seq->ps * SPSIZE * sizeof(void*));
    }
}

/* insert a val at idx into sequence */
void
mg_sequence_insert (Sequence *seq, int idx, void *val)
{
  for (int i = seq->size - 1; i >= idx; i--)
    seq->elts[i+1] = seq->elts[i];
  seq->elts[idx] = val;
  seq->size = seq->size + 1;
}

/* set a val at idx of sequence */
void
mg_sequence_set (Sequence *seq, int idx, void *val)
{
  seq->elts[idx] = val;
}

/* remove a val at idx of sequence */
void
mg_sequence_remove (Sequence *seq, int idx)
{
  for (int i = idx; i <= seq->size; i++)
    seq->elts[i] = seq->elts[i+1];
  seq->size = seq->size - 1;
}

/* get a val at idx of sequence */
void *
mg_sequence_get (Sequence *seq, int idx)
{
  return seq->elts[idx];
}

/* reverse the sequence */
void
mg_sequence_reverse (Sequence *seq)
{
  for (int i = 0, j = seq->size - 1; i < seq->size / 2; i++, j--)
    {
      void *tmp = seq->elts[i];
      seq->elts[i] = seq->elts[j];
      seq->elts[j] = tmp;
    }
}

/* call mgfunc on each element */
void
mg_sequence_foreach (Sequence *seq, MgFunc mgfunc)
{
  for (int i = 0; i < seq->size; i++)
    mgfunc (seq->elts[i]);
}

/* ---------------------------------------- */

/* define function for MgFunc to output long int */
void
out_longint (void *val)
{
  printf ("%ld ", (long)(val));
}

/**/
void
test_sequence_longint (void)
{
  Sequence *seq = mg_sequence_new ();

  for (long i = 0; i < 10; i++)
    mg_sequence_append (seq, (void*)(i + 1000));

  printf ("Test sequence new, append, foreach method:\n");
  mg_sequence_foreach (seq, out_longint);

  printf ("\nTest sequence insert method:\n");
  mg_sequence_insert (seq, 5, (void*)(8888));
  mg_sequence_foreach (seq, out_longint);

  printf ("\nTest sequence reverse method:\n");
  mg_sequence_reverse (seq);
  mg_sequence_foreach (seq, out_longint);

  printf ("\nTest sequence remove method:\n");
  mg_sequence_remove (seq, 5);
  mg_sequence_foreach (seq, out_longint);

  printf ("\nSequence page size : %d\n", SPSIZE);
  printf ("Sequence size : %d\n", seq->size);
  printf ("Sequence page : %d\n", seq->ps);

  printf ("Sequence val at index 9 is %ld\n", (long)mg_sequence_get(seq, 9));

  mg_sequence_free (seq);
}

/* define function for MgFunc to output char* */
void
out_string (void *val)
{
  printf ("%s ", (char*)val);
}

/* */
void
test_sequence_string (void)
{
  char *buff[6] = {"Not", "Only", "Test", "Here", "Another", "Behind"};
  Sequence *seq = mg_sequence_new ();
  for (int i = 0; i < 6; i++)
    mg_sequence_append (seq, buff[i]);
  mg_sequence_foreach(seq, out_string);
  printf ("\n");
  mg_sequence_free (seq);
}

/* */
void
test_sequence_string_malloc (void)
{
  Sequence *seq = mg_sequence_new ();

  for (int i = 1000; i < 1010; i++)
    {
      char *buf = (char*) malloc (16);
      sprintf (buf, "demo-%d", i);
      mg_sequence_append (seq, buf);
    }

  mg_sequence_foreach(seq, out_string);
  printf ("\n");

  mg_sequence_free_elements (seq);
  mg_sequence_free (seq);
}

/**/
int
main (int argc, char *argv[])
{
  //test_sequence_longint ();
  test_sequence_string ();
  test_sequence_string_malloc ();
  return 0;
}
/* -----(:/.^.\:)-----*/

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/soo$ gcc seqv.c -o seqv
songvm@ubuntu:~/works/xdn/soo$ ./seqv
Not Only Test Here Another Behind 
demo-1000 demo-1001 demo-1002 demo-1003 demo-1004 demo-1005 demo-1006 demo-1007 demo-1008 demo-1009 
songvm@ubuntu:~/works/xdn/soo$ valgrind --leak-check=yes ./seqv
==10181== Memcheck, a memory error detector
==10181== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==10181== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==10181== Command: ./seqv
==10181== 
Not Only Test Here Another Behind 
demo-1000 demo-1001 demo-1002 demo-1003 demo-1004 demo-1005 demo-1006 demo-1007 demo-1008 demo-1009 
==10181== 
==10181== HEAP SUMMARY:
==10181==     in use at exit: 0 bytes in 0 blocks
==10181==   total heap usage: 16 allocs, 16 frees, 1,472 bytes allocated
==10181== 
==10181== All heap blocks were freed -- no leaks are possible
==10181== 
==10181== For counts of detected and suppressed errors, rerun with: -v
==10181== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
songvm@ubuntu:~/works/xdn/soo$ 

结果如预期!下一步研究字符串!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值