Data structure linear table (sequence table, single chain table)

Keywords: C++

Linear table

1. Meaning of linear table

linear list is a finite sequence of n data elements with the same characteristics Linear table is a kind of data structure widely used in practice. Common linear table: sequence table, chain table, stack, queue, string... Linear table is a linear structure in logic, that is to say, a continuous line. But it is not necessarily continuous in physical structure. When linear table is stored in physical structure, it is usually stored in the form of array and chain structure.

2. Diagram of linear table

    


Sequence table

Single linked list

4. Code implementation

common.h

#ifndef _COMMON_H_
#define _COMMON_H_
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>
typedef enum{FALSE, TRUE} BOOL;
#define DataType int
#define DEFAULT_SIZE 8
#define INC_SIZE      3
void Swap(DataType *a, DataType *b)
{
 DataType tmp = *a;
 *a = *b;
 *b = tmp;
}
#endif /* _COMMON_H_ */

seqlist.h

Sequential table is a linear structure in which data elements are sequentially stored in a continuous storage unit with a physical address. Generally, array storage is used. Add, delete, check and modify the data on the array.

The sequence table can be generally divided into:
1). Static sequence table: stored with fixed length array.

2). Dynamic sequence table: use dynamic array storage.

#ifndef _SEQLIST_H_
#define _SEQLIST_H_
#define NULL_DATA -1
typedef struct SeqList
{
 DataType *base;
 size_t    capacity;
 size_t    size;
}SeqList;
//Internal method
static BOOL _Inc(SeqList *psl);
BOOL SeqListIsFull(SeqList *psl);
BOOL SeqListIsEmpty(SeqList *psl);
void SeqListInit(SeqList* psl, size_t capacity);
void SeqListPushBack(SeqList* psl, DataType x);
void SeqListShow(SeqList *psl);
void SeqListPopBack(SeqList* psl);
void SeqListPopFront(SeqList* psl);
size_t SeqListLength(SeqList *psl);
void SeqListClear(SeqList *psl);
DataType SeqListFindByPos(SeqList *psl, int pos);
int SeqListFindByVal(SeqList *psl, DataType key);
BOOL SeqListEraseByVal(SeqList *psl, DataType key);
BOOL SeqListEraseByPos(SeqList *psl, int pos);
BOOL SeqListInsertByPos(SeqList *psl, int pos, DataType x);
void SeqListReverse(SeqList *psl);
void SeqListRemoveAll(SeqList* psl, DataType x);
void SeqListSort(SeqList *psl);
void SeqListDestroy(SeqList *psl);
BOOL _Inc(SeqList *psl)
{
 DataType *new_base = 
  (DataType *)malloc(sizeof(DataType)*(psl->capacity + INC_SIZE));
 if (new_base == NULL)
  return FALSE;
 
 memcpy(new_base, psl->base, sizeof(DataType)*psl->capacity);
 free(psl->base);
 psl->base = new_base;
 psl->capacity += INC_SIZE;
 return TRUE;
}
BOOL SeqListIsFull(SeqList *psl)
{
 if (psl->size >= psl->capacity)
  return TRUE;
 return FALSE;
}
BOOL SeqListIsEmpty(SeqList *psl)
{
 if (psl->size == 0)
  return TRUE;
 return FALSE;
}
////////////////////////////////////////////////////////////
void SeqListInit(SeqList* psl, size_t capacity)
{
 psl->base = (DataType*)malloc(sizeof(DataType)*capacity);
 assert(psl->base != NULL);
 psl->capacity = capacity;
 psl->size = 0;
}
void SeqListPushBack(SeqList* psl, DataType x)
{
 if (SeqListIsFull(psl) && !_Inc(psl))
 {
  printf("Order table space full,%d Can not be inserted.\n", x);
  return;
 }
 psl->base[psl->size++] = x;
}
void SeqListPushFront(SeqList* psl, DataType x)
{
 if (SeqListIsFull(psl) && !_Inc(psl))
 {
  printf("Order table space full,%d Can not be inserted.\n", x);
  return;
 }
 for (int i = psl->size; i > 0; --i)
 {
  psl->base[i] = psl->base[i - 1];
 }
 psl->base[0] = x;
 psl->size++;
}
void SeqListShow(SeqList *psl)
{
 for (int i = 0; i < psl->size; ++i)
 {
  printf("%d ", psl->base[i]);
 }
 printf("\n");
}
void SeqListPopBack(SeqList* psl)
{
 if (SeqListIsEmpty(psl))
 {
  printf("The sequence table is empty and cannot be deleted.\n");
  return;
 }
 psl->size--;
}
void SeqListPopFront(SeqList* psl)
{
 if (SeqListIsEmpty(psl))
 {
  printf("The sequence table is empty and cannot be deleted.\n");
  return;
 }
 for (int i = 0; i<psl->size-1; ++i)
 {
  psl->base[i] = psl->base[i + 1];
 }
 psl->size--;
}
size_t SeqListLength(SeqList *psl)
{
 return psl->size;
}
void SeqListClear(SeqList *psl)
{
 psl->size = 0;
}
DataType SeqListFindByPos(SeqList *psl, int pos)
{
 //assert(pos >= 0 && pos < psl->size);
 if (pos < 0 || pos >= psl->size)
 {
  printf("Invalid location for query.\n");
  return NULL_DATA;
 }
 return psl->base[pos];
}
int SeqListFindByVal(SeqList *psl, DataType key)
{
 for (int i = 0; i < psl->size; ++i)
 {
  if (key == psl->base[i])
   return i;
 }
 return -1;
}
BOOL SeqListEraseByPos(SeqList *psl, int pos)
{
 if (pos < 0 || pos >= psl->size)
  return FALSE;
 for (int i = pos; i < psl->size - 1; ++i)
  psl->base[i] = psl->base[i + 1];
 psl->size--;
 return TRUE;
}
BOOL SeqListEraseByVal(SeqList *psl, DataType key)
{
 int index = SeqListFindByVal(psl, key);
 if (index == -1)
  return FALSE;
 return SeqListEraseByPos(psl, index);
}
BOOL SeqListInsertByPos(SeqList *psl, int pos, DataType x)
{
 if (pos<0 || pos>psl->size)
  return FALSE;
 if (SeqListIsFull(psl) && !_Inc(psl))
 {
  printf("Order table space full,%d Can not be inserted.\n", x);
  return FALSE;
 }
 for (int i = psl->size; i > pos; --i)
  psl->base[i] = psl->base[i - 1];
 psl->base[pos] = x;
 psl->size++;
 return TRUE;
}
void SeqListReverse(SeqList *psl)
{
 if (psl->size >= 2)
 {
  int begin = 0;
  int end = psl->size - 1;
  while (begin < end)
  {
   Swap(&(psl->base[begin]), &(psl->base[end]));
   begin++;
   end--;
  }
 }
}
void SeqListRemoveAll(SeqList* psl, DataType x)
{
 for (int i = 0; i < psl->size; ++i)
 {
  if (x == psl->base[i])
  {
   for (int j = i; j < psl->size-1; ++j)
    psl->base[j] = psl->base[j + 1];
   psl->size--;
   i--;
  }
 }
}
void SeqListSort(SeqList *psl)
{
 for (int i = 0; i < psl->size - 1; ++i)
 {
  for (int j = 0; j < psl->size - i - 1; ++j)
  {
   if (psl->base[j] > psl->base[j + 1])
   {
    Swap(&(psl->base[j]), &(psl->base[j + 1]));
   }
  }
 }
}
void SeqListDestroy(SeqList *psl)
{
 free(psl->base);
 psl->base = NULL;
 psl->capacity = psl->size = 0;
}

slist.h

Linked list is a kind of non continuous and non sequential storage structure in physical storage structure. The logical order of data elements is realized by the order of pointer link in linked list

#ifndef _SLIST_H_
#define _SLIST_H_
#include"common.h"
typedef struct SListNode
{
 DataType data;
 struct SListNode *next; //link
}SListNode;
typedef struct SList
{
 SListNode *first;
 SListNode *last;
 size_t     size;
}SList;

SListNode* _Buynode(DataType x)
{
 SListNode *s = (SListNode *)malloc(sizeof(SListNode));
 assert(s != NULL);
 s->data = x;
 s->next = NULL;
 return s;
}
void SListInit(SList* plist);
void SListPushBack(SList *plist, DataType x);
void SListPushFront(SList *plist, DataType x);
void SListShow(SList *plist);
SListNode* SListFindByVal(SList *plist, DataType key);
BOOL SListEraseByVal(SList *plist, DataType key);
void SListInit(SList* plist)
{
 SListNode *s = _Buynode(0);
 plist->first = plist->last = s;
 plist->size = 0;
}
void SListPushBack(SList *plist, DataType x)
{
 assert(plist != NULL);
 SListNode *s = _Buynode(x);
 plist->last->next = s;
 plist->last = s;
 plist->size++;
}
void SListPushFront(SList *plist, DataType x)
{
 assert(plist != NULL);
 SListNode *s = _Buynode(x);
 s->next = plist->first->next;
 plist->first->next = s;
 //Determine whether the first node is inserted
 if (plist->size == 0)
  plist->last = s;
 plist->size++;
}
void SListShow(SList *plist)
{
 SListNode *p = plist->first->next;
 while (p != NULL)
 {
  printf("%d-->", p->data);
  p = p->next;
 }
 printf("Over.\n");
}
SListNode* SListFindByVal(SList *plist, DataType key)
{
 assert(plist != NULL);
 SListNode *p = plist->first->next;
 while (p != NULL && p->data != key)
  p = p->next;
 return p;
}
BOOL SListEraseByVal(SList *plist, DataType key)
{
 assert(plist != NULL);
 SListNode *p, *q;
 p = SListFindByVal(plist, key);
 if(p == NULL)
  return FALSE;
 q = p->next;
 if (q == plist->last)
  plist->last = p;
 p->data = q->data;
 p->next = q->next;
 free(q);
 plist->size--;
 return TRUE;
}
#if 0
typedef SListNode *List;
//////////////////////////////////////////////////
void SListInit(List *head);
void SListCreate_Back(List *head);
void SListCreate_Front(List *head);
void SListCreate_Back1(List *head);
void SListShow(List head);
SListNode* _Buynode(DataType x)
{
 SListNode *s = (SListNode *)malloc(sizeof(SListNode));
 assert(s != NULL);
 s->data = x;
 s->next = NULL;
 return s;
}
void SListInit(List *head)
{
 *head = _Buynode(0);
}
void SListCreate_Back(List *head)
{
 SListNode *p = *head;
 for(int i=1; i<=10; ++i)
 {
  SListNode *s = _Buynode(i);
  p->next = s;
  p = s;
 }
}
void SListCreate_Front(List *head)
{
 for (int i = 1; i <= 10; ++i)
 {
  SListNode *s = _Buynode(i);
  s->next = (*head)->next;
  (*head)->next = s;
 }
}
void SListShow(List head)
{
 SListNode *p = head->next;
 while (p != NULL)
 {
  printf("%d-->", p->data);
  p = p->next;
 }
 printf("Over.\n");
}
void SListInit(List *head)
{
 *head = NULL;
}
void SListCreate_Back(List *head)
{
 *head = (SListNode*)malloc(sizeof(SListNode));
 assert(*head != NULL);
 (*head)->data = 1;
 (*head)->next = NULL;
 SListNode *p = *head;
 for (int i = 2; i <= 10; ++i)
 {
  SListNode *s = (SListNode*)malloc(sizeof(SListNode));
  assert(s != NULL);
  s->data = i;
  s->next = NULL;
  p->next = s;
  p = s;
 }
}
void SListCreate_Front(List *head)
{
 //1 create the first node
 *head = (SListNode*)malloc(sizeof(SListNode));
 assert(*head != NULL);
 (*head)->data = 1;
 (*head)->next = NULL;
 //2. Cycle to create nodes for head insertion
 for (int i = 2; i <= 10; ++i)
 {
  SListNode *s = (SListNode*)malloc(sizeof(SListNode));
  assert(s != NULL);
  s->data = i;
  s->next = *head;
  *head = s;
 }
}
void SListCreate_Back1(List *head)
{
 *head = (SListNode*)malloc(sizeof(SListNode));
 assert(*head != NULL);
 (*head)->data = 1;
 (*head)->next = NULL;
 SListNode *p = *head;
 for (int i = 2; i <= 10; ++i)
 {
  p = p->next = (SListNode*)malloc(sizeof(SListNode));
  assert(p != NULL);
  p->data = i;
  p->next = NULL;
 }
}
void SListShow(List head)
{
 SListNode *p = head;
 while (p != NULL)
 {
  printf("%d-->", p->data);
  p = p->next;
 }
 printf("Over.\n");
}
#endif

test.c

#include"common.h"
#include"seqlist.h"
#include"slist.h"
int main(int argc, char *argv[])
{
 //SeqList mylist;
 SListNode *p = NULL;
 SList mylist;
 SListInit(&mylist);
 DataType item;
 int pos, index;
 BOOL flag;
 int select = 1;
 while (select)
 {
  printf("************************************\n");
  printf("* [1] push_back     [2] push_front *\n");
  printf("* [3] show_list     [0] quit_system*\n");
  printf("* [4] pop_back      [5] pop_front  *\n");
  printf("* [6] find_pos      [7] find_val   *\n");
  printf("* [8] insert_pos    [9] delete_val *\n");
  printf("* [10] delete_pos   [11]length     *\n");
  printf("* [12] remove_all   [13] reverse   *\n");
  printf("* [14] sort         [15] clear     *\n");
  printf("************************************\n");
  printf("Please choose:>");
  scanf("%d", &select);
  if (select == 0)
   break;
  switch (select)
  {
  case 1:
   printf("Please enter the data to insert(with-1 End):>");
   while (scanf("%d", &item), item != -1)
   {
    SListPushBack(&mylist, item);
   }
   break;
  case 2:
   printf("Please enter the data to insert(with-1 End):>");
   while (scanf("%d", &item), item != -1)
   {
    SListPushFront(&mylist, item);
   }
   break;
  case 3:
   SListShow(&mylist);
   break;
  case 4:
   //SeqListPopBack(&mylist);
   break;
  case 5:
   //SeqListPopFront(&mylist);
   break;
  case 6:
   printf("Please enter the location to query:>");
   scanf("%d", &pos);
   //printf("data to query:% d\n", & seqlistfindbypos (& mylist, pos));
   break;
  case 7:
   printf("Please enter the data to query:>");
   scanf("%d", &item);
   //index = SeqListFindByVal(&mylist, item);
   p = SListFindByVal(&mylist, item);
   if (p==NULL)
    printf("Data to query%d Non-existent.\n", item);
   break;
  case 8:
   printf("Please enter the location to insert:>");
   scanf("%d", &pos);
   printf("Please enter the data to insert:>");
   scanf("%d", &item);
   //flag = SeqListInsertByPos(&mylist, pos, item);
   if (flag)
    printf("Insert success.\n");
   else
    printf("Insert failure.\n");
   break;
  case 9:
   printf("Please enter the data to delete:>");
   scanf("%d", &item);
   //flag = SeqListEraseByVal(&mylist, item);
   SListEraseByVal(&mylist, item);
   break;
  case 10:
   printf("Please enter the location to delete:>");
   scanf("%d", &pos);
   //flag = SeqListEraseByPos(&mylist, pos);
   if (flag)
    printf("Delete successful.\n");
   else
    printf("Delete failed.\n");
   break;
  case 11:
   printf("SeqList Length = %d\n", SeqListLength(&mylist));
   break;
  case 12:
   printf("Please enter the data to delete:>");
   scanf("%d", &item);
   //SeqListRemoveAll(&mylist, item);
   break;
  case 13:
   //SeqListReverse(&mylist);
   break;
  case 14:
   //SeqListSort(&mylist);
   break;
  case 15:
   //SeqListClear(&mylist);
   break;
  }
 }
 //SeqListDestroy(&mylist);
 return 0; 
}

Because these two test methods are almost the same, only one test function is used. These two data structures belong to linear structure. Of course, there are many linear structures, and some other linear tables will be published later



Posted by bigswifty on Tue, 19 Nov 2019 04:12:56 -0800