本文讨论最简单最基本的一种数据结构:表。
我们将处理一般的形如A1,A2,A3.....AN的表。这个表的大小为N。我们称大小为0的表为空表。
1、表的简单数组实现
对表的所有操作都可以通过数组来实现。我们假定数据量为10个,所以我们可以设置一个有10个元素的数组。同时为了表示数组的位置,再定义一个表示数组位置的变量
#define N 10
typedef int data_t;
typedef struct
{
data_t a[10];
int last;
}sqlist;
用这个结构体我们可以实现一个简单的表。
1.1 数组表的创建
表的创建很简单,我们用一个指针来指向这个表,只要开辟响应的空间即可,并将数组位置last置为-1
sqlist *sqlist_creat()
{
sqlist * sqlist_node = (sqlist *)malloc(sizeof(sqlist));
sqlist_node->last = -1;
return sqlist;
}
1.2 添加
向表的最后添加一个数据
data_t sqlist_add_tail(sqlist *list,data_t value)
{
list->a[list->last] = value;
list->last++;
}
但是,由于数组是有数量的,有可能出现满的情况,所以要先判断一下数组是否已经满加入到上面的函数中
int is_full(sqlist *list)
{
return list->last == N-1?1:0;
}
data_t sqlist_add_tail(sqlist *list,data_t value)
{
if(is_full(list))
{
printf("list is full\n");
return -1;
}
list->last++;
list->a[list->last] = value;
return 0;
}
1.3 删除一个元素
添加时要判断是为满,同样删除时候要先判断一下是否为空。
int is_empty(sqlist *list)
{
return list->last == -1?1:0;
}
删除元素,删除一个元素时,我们必须将其后面的元素依次往前移动。
data_t sqlist_delete(sqlist *list,data_t value)
{
int i=0;
int j = 0;
if(is_empty(list))
{
printf("list is empty\n");
return -1;
}
for(i=0;i<=list->last;i++)
{
if(list->a[i] == value)
{
for(j=i;j<list->last;j++)
{
list->a[j] = list->a[j+1];
}
list->last--;
}
}
return 0;
}
2、链表
为了避免插入和删除的线性开销,我们可以使表不连续存储。为此我们可以设置这样的节点:一个数据,一个地址,地址指向下一个节点。
2.1 链表创建
定义以下变量
typedef int data_t;
typedef struct node
{
data_t data;
struct node * next;
}link_node;
在创建链表时,我们先创建一个头节点head,这个节点没有数据,地址指向为NULL,这也就是单向链表。
link_node *list_creat()
{
link_node *head = (link_node *)malloc(sizeof(link_node));
head->next = NULL;
return head;
}
2.2 链表添加
链表的添加分为头插入、尾插入和任意位置擦汗如,也就是新节点添加位置的区别。
2.2.1 头插入添加
头添加过程如下
首先将原先的第一个节点地址给要添加的节点,
然后将要添加的节点地址给头节点head
这两步不能反,先执行第二步会使得无法找到原来第一个节点了(当然你可以使用临时变量)。与数组表不同的是,链表不存在满的情况,所以不用判断是否为满。
int link_list_add(link_node *head,data_t value)
{
link_node *node = (link_node *)malloc(sizeof(link_node));
node->data = value;
node->next = head->next;
head->next = node;
return 0;
}
2.2.2 尾插入添加
尾插入的方法就是将新节点添加到链表的最后
int link_list_add_tail(link_node *head, data_t value)
{
link_node *node = (link_node *)malloc(sizeof(link_node));
node->data = value;
node->next = NULL;
while(head->next!=NULL)
{
head = head->next;
}
head->next = node;
}
2.3 链表删除
与链表添加一样,删除也可以分为头删除和尾删除
2.3.1 头删除
删除前首先需要判断链表是否为空。头删除后要把不用的节点指向NULL防止野指针。
int is_empty(link_node *head)
{
return head->next==NULL?1:0;
}
int link_list_del(link_node *head)
{
if(is_empty(head))
{
printf("is empty\n");
return -1;
}
link_node *temp = head->next;
head->next = temp->next;
temp = NULL;
}
2.3.2 尾删除
尾删除是删除最后一个节点,所以要找到倒数第二个节点
int link_list_del_tail(link_node *head)
{
link_node *temp = NULL;
if(is_empty(head))
{
printf("is empty\n");
return -1;
}
while(head->next->next!=NULL)
{
head = head->next;
}
temp = head->next;
head->next = NULL;
temp = NULL;
return 0;
}