1、定义:线性表是具有相同类型的n(>=0)个数据元素的有限序列。
2、性质:
线性表的第一个元素只有一个后继,最后一个元素只有一个前驱,其他的元素既有前驱又有后继,线性表能够逐项访问和顺序存取。
3、线性表的操作:
创建线性表、销毁线性表、清空线性表、将元素插入线性表、将元素从线性表中删除、获取线性表中某个位置的元素、获取线性表的长度。
4、实现线性表:
线性表在程序中表型为一种特殊的数据类型;线性表的操作在程序中的表现为一组函数。
List* List_Create();
void List_Destroy(List* list);
void List_Clear(List* list);
int List_Insert(List* list, ListNode* node, int pos);
ListNode* List_Delete(List* list, int pos);
ListNode* List_Get(List* list, int pos);
int List_Length(List* list);
顺序存储定义:
线性变的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。
在C语言中可以用一维数组来实现顺序存储结构:
存储空间的起始位置:数组node
线性表的最大容量:数组长度MAXSIZE
线性表的当前长度:length
#define MAXSIZE 20
typedef struct _tag_List
{
char node[MAXSIZE];
int length;
}List;
获取元素的操作:
判断线性表是否合法;
判断位置是否合法;
直接通过数组小标的方式获取元素;
char Get(List* list, int pos)
{
char ret = -1;
/*判断线性表的合法性,判断位置的合法性*/
if( (list != NULL) && (0 <= pos) && (pos < list->length) )
{
ret = list->nose[pos];
}
return ret;
}
插入元素操作:
判断线性表是否合法;
判断插入位置是否合法;
把最后一个元素到插入位置的元素后移一个位置
将新元素插入;
线性表长度加1;
插入元素算法:
int Insert(List* list, char c, int pos)
{
/*判断线性表合法性*/
int ret = (list != NULL);
int i = 0;
/*判断插入位置合法性*/
ret = ret && (list->length + 1 <= MAXSIZE);
ret = ret && (0 <= pos);
if(ret)
{
if( pos >= list->length )
{
pos = list->length;
}
/*从最后一个元素开始到第pos个位置分别将它们向后移一个位置*/
for( i = list->length; i>pos; i--)
{
list->node[i] = list->node[i-1];
}
list->node[i] = c;//将新元素插入
list->length++; //将线性表长度加1
}
return ret;
}
删除元素算法
判断线性表是否合法;
判断删除的位置是否合法;
将元素取出;
将删除位置后的元素分别向前移动一个位置
线性表长度减1;
char Delete(List* list, int pos)
{
char ret = -1;
int i = 0;
/*判断线性表是否合法,判断删除位置是否合法*/
if( (list != NULL) && (0 <=pos) && (pos < list->length) )
{
/*取出删除元素*/
ret = list->node[pos];
/*将删除位置pos以后的元素分别向前移动一个位置*/
for( i = pos + 1; i < list->length; i++)
{
list->node[i-1] = list->node[i];
}
list->length--; //线性表长度减1;
}
return ret;
}
-
/*SeqList.h*/
-
********************************************************
-
#ifndef _SEQLIST_H_
-
#define _SEQLIST_H_
-
-
typedef void SeqList;
-
typedef void SeqListNode;
-
-
SeqList* SeqList_Create(int capacity);
-
-
void SeqList_Destroy(SeqList* list);
-
-
void SeqList_Clear(SeqList* list);
-
-
int SeqList_Length(SeqList* list);
-
-
int SeqList_Capacity(SeqList* list);
-
-
int SeqList_Insert(SeqList* list, SeqListNode* node, int pos);
-
-
SeqListNode* SeqList_Delete(SeqList* list, int pos);
-
-
SeqListNode* SeqList_Get(SeqList* list, int pos);
-
-
#endif
-
*******************************************************
-
/*main.c*/
-
*************************************************************************
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include "SeqList.h"
-
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
-
-
int main(int argc, char *argv[])
-
{
-
SeqList* list = SeqList_Create(5);
-
int i = 0;
-
int j = 1;
-
int k = 2;
-
int x = 3;
-
int y = 4;
-
int z = 5;
-
int index = 0;
-
-
SeqList_Insert(list, &i, 0);
-
SeqList_Insert(list, &j, 0);
-
SeqList_Insert(list, &k, 0);
-
SeqList_Insert(list, &x, 0);
-
SeqList_Insert(list, &y, 0);
-
SeqList_Insert(list, &z, 0);
-
for(index=0; index<SeqList_Length(list);index++)
-
{
-
int* p = (int*)SeqList_Get(list,index);
-
printf("%d\n",*p);
-
}
-
printf("\n");
-
while( SeqList_Length(list) > 0)
-
{
-
int* p = (int*)SeqList_Delete(list,0);
-
printf("%d\n",*p);
-
}
-
SeqList_Destroy(list);
-
return 0;
-
}
该存储方式的优点在于无需为线性表中的逻辑关系增加额外的空间,可以快速的获取表中合法位置的元素;缺点在于插入和删除操作需要移动大量的元素,当线性表长度变化比较大时难以确定存储空间的容量。
链式存储结构:
定义:为了表示每个数据元素与其直接后继元素之间的逻辑关系,每个元素除了存储本身的信息外,还需要存储指示直接后继的信息。
链式存储逻辑结构:
n个结点链接成一个链式线性表的结构叫做链表,当每个结点中止包含一个指针域时,叫做单链表。
链表的基本概念:
表头结点:链表中的第一个结点,包含指向第一个数据元素的指针以及链表自身的一些信息。
数据结点:链表中代表数据元素的结点,包含指向下一个数据元素的指针和数据元素的信息。
尾结点:链表中的最后一个数据结点,其下一元素指针为空,表示无后继。
在C语言中可以用结构体来定义链表中的指针域,链表中的头结点也可以用结构体实现
结点指针域定义:
typedef struct _tag_LinkListNode LinkListNode;
struct _tag_LinkListNode
{
LinkListNode* next;
};
头结点定义:
typedef struct _tag_LinkList
{
LinkListNode header;
int length;
}TLinkList;
数据元素定义示例:
struct Value
{
LinkListNode header;
int v;
};
获取第pos个元素操作
判断线性表是否合法;
判断位置是否合法;
由表头开始通过next指针移动pos后,当前元素的next指针即指向要获取的元素;
LinkListNode* current = (LinkListNode*)list;
for(i=0; i
{
current = current->next;
}
ret = current->next;
插入元素到位置pos的算法
判断线性表是否合法;
判断插入位置是否合法;
由表头开始通过next指针移动pos后,当前元素的next指针即指向要插入的位置;
将新元素插入;
线性表长度加1;
LinkListNode* current = (LinkListNode*)list;
for(i=0; (i < pos) && (current->next != NULL); i++)
{
current = current->next;
}
node->next = current->next;
current->next = node;
sList->length++;
删除第pos个元素的算法
判断线性表的合法性;
判断插入位置是否合法;
获取第pos个元素;
将第pos个元素从链表中删除
线性表长度减1;
TLinkList* sList = (TLinkList*)list
LinkListNode* ret = NULL;
int i = 0;
if( (sList != NULL) && (0<=pos) && (pos < sList->length) )
{
LinkListNode* current = (LinkListNode*)list;
{
current = current->next;
}
ret = current->next;
current->next = ret->next;
sList->length--;
}
-
/*LinkList.h*/
-
*******************************************************************
-
#ifndef _LINKLIST_H_
-
#define _LINKLIST_H_
-
-
typedef void LinkList;
-
typedef struct _tag_LinkListNode LinkListNode;
-
struct _tag_LinkListNode
-
{
-
LinkListNode* next;
-
};
-
-
LinkList* LinkList_Create();
-
-
void LinkList_Destroy(LinkList* list);
-
-
void LinkList_Clear(LinkList* list);
-
-
int LinkList_Length(LinkList* list);
-
-
int LinkList_Insert(LinkList* list, LinkListNode* node, int pos);
-
-
LinkListNode* LinkList_Get(LinkList* list, int pos);
-
-
LinkListNode* LinkList_Delete(LinkList* list, int pos);
-
-
#endif
**********************************************************************
-
/*main.c*/
-
*************************************************************************
-
#include <stdio.h>
-
#include <stdlib.h>
-
#include "LinkList.h"
-
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
-
-
struct Value
-
{
-
LinkListNode header;
-
int v;
-
};
-
-
int main(int argc, char *argv[])
-
{
-
int i = 0;
-
LinkList* list = LinkList_Create();
-
-
struct Value v1;
-
struct Value v2;
-
struct Value v3;
-
struct Value v4;
-
struct Value v5;
-
-
v1.v = 1;
-
v2.v = 2;
-
v3.v = 3;
-
v4.v = 4;
-
v5.v = 5;
-
-
LinkList_Insert(list, (LinkListNode*)&v1, LinkList_Length(list));
-
LinkList_Insert(list, (LinkListNode*)&v2, LinkList_Length(list));
-
LinkList_Insert(list, (LinkListNode*)&v3, LinkList_Length(list));
-
LinkList_Insert(list, (LinkListNode*)&v4, LinkList_Length(list));
-
LinkList_Insert(list, (LinkListNode*)&v5, LinkList_Length(list));
-
-
for(i=0; i<LinkList_Length(list); i++)
-
{
-
struct Value* pv = (struct Value*)LinkList_Get(list, i);
-
-
printf("%d\n", pv->v);
-
}
-
-
while( LinkList_Length(list) > 0 )
-
{
-
struct Value* pv = (struct Value*)LinkList_Delete(list, 0);
-
-
printf("%d\n", pv->v);
-
}
-
-
LinkList_Destroy(list);
-
-
return 0;
-
}
线性表的链式结构的优点是无需一次性定制链表的容量,插入和删除操作无需移动数据元素;
不足是数据元素必须保存后继元素的位置信息,获取指定数据的元素操作需要顺序访问之前的元素。
阅读(3196) | 评论(0) | 转发(0) |