您的位置:首页 > 编程语言 > C语言/C++

顺序表、单链表——C语言实现及其比较

2018-02-09 00:00 441 查看
摘要: 这是一个C语言实现顺序表和单链表的完整例子,可在Dev C++5.11上完美运行。在后面对两者的时间性能和空间性能进行了比较。

(一)顺序表的实现

顺序表的存储结构定义

#define MaxSize 100
typedef int DataType;
typedef struct
{
DataType data[MaxSize];	//存储数组
int length;	//顺序表的长度
} seqList;

顺序表的实现

函数声明

/* 函数声明 */
//	1)、初始化顺序表
void initList(seqList *L);
//	2)、建立顺序表
int creatList(seqList *L, DataType arr[], int n);
//	3)、销毁顺序表 :顺序表是静态存储分配,在顺序表变量退出作用域时自动释放所占内存单元
//	4)、判空操作
int isEmpty(seqList *L);
//	5)、求顺序表的长度
int getLength(seqList *L);
//	6)、遍历操作
int printList(seqList *L);
//	7)、按值查找
int locate(seqList *L, DataType n);
//	8)、按位查找
/*
L:顺序表指针
i:需要查找第几个元素
ptr:存储查找到的元素
*/
int get(seqList *L, DataType i, DataType *ptr);
//	9)、插入操作
/*
L:顺序表的指针
i:需要插入到第几个元素
x:插入元素的值
*/
int insert(seqList *L, DataType i, DataType x);
// 10)、按位删除
/*
L:顺序表指针
i:需要删除第几个元素
ptr:存储删除的元素
*/
int deleteByPosition(seqList *L, DataType i, DataType *ptr);

测试

/* 测试 */
int main()
{
int arr[] = {3,2,8,4,9};
int i;
seqList L;
creatList(&L, arr, 5);

i = getLength(&L);
printf("顺序表长度:%d\n", i);
if(isEmpty)
{
printf("顺序表非空\n");
}
printf("遍历顺序表:");
printList(&L);
printf("\n");

int flag = locate(&L, 4);
if(flag)
{
printf("查找成功,序号为:%d\n", flag);

}
else
{
printf("查找失败\n");
}

int x;
printf("请输入你要查找元素的位置:");
scanf("%d", &i);
if(get(&L, i, &x))
{
printf("第%d个元素为:%d\n", i,x);
}

if(insert(&L, 2, 22))
{
printf("插入元素后:");
printList(&L);
printf("\n");
}

int position, y;
printf("请输入需要删除元素的位置:\n");
scanf("%d", &position);
if(deleteByPosition(&L, position, &y))
{
printf("删除的元素为%d\t删除元素后:", y);
printList(&L);
printf("\n");
}
}

函数定义

/* 函数定义 */
void initList(seqList *L)
{
L->length = 0;
}

/*
L :顺序表的指针
arr:传入的数组
n:需要建立的顺序表的长度

创建成功返回 1,否则返回 0
*/
int creatList(seqList *L, DataType arr[], int n)
{
if(n > MaxSize)
{
printf("顺序表的存储空间不足,创建失败!");
return 0;
}
for(int i = 0; i< n; i++)
{
L->data[i] =
7fe0
arr[i];
}
L->length = n;
return 1;
}

int isEmpty(seqList *L)
{
if(L->length == 0)
return 1;
else
return 0;
}

int getLength(seqList *L)
{
return L->length;
}

int printList(seqList *L)
{
for(int i = 0; i< L->length; i++)
{
printf("%d\t", L->data[i]);
}
}

int locate(seqList *L, DataType n)
{
for(int i = 0; i< L->length; i++)
{
if(L->data[i] == n)
return i+1;
}
return 0;
}

int get(seqList *L, DataType i, DataType *ptr)
{
if(i < 1 || i > L->length)
{
printf("查找地址非法,查找失败\n");
return 0;
}
else
{
*ptr = L->data[i-1];
return 1;
}
}

int insert(seqList *L, DataType i, DataType x)
{
if(L->length >= MaxSize)
{
printf("上溢错误,插入失败\n");
}
if(i < 1 || i > L->length+1)
{
printf("插入位置错误,插入失败\n");
return 0;
}
for(int j = L->length; j>= i; j--)
{
L->data[j] = L->data[j-1];
}
L->data[i-1] = x;
L->length++;
return 1;
}

int deleteByPosition(seqList *L, DataType i, DataType *ptr)	//  ?
{
if(L->length == 0)
{
printf("下溢错误,删除失败\n");
return 0;
}
if(i < 0 || i > L->length )
{
printf("位置错误,删除失败\n");
return 0;
}
*ptr = L->data[i-1];
for(int j = i; j< L->length; j++)
{
L->data[j-1] = L->data[j];
}
L->length--;
return 1;
}

运行效果



(二)单链表的实现

单链表的存储结构定义

/* 单链表的存储结构定义 */
typedef int DataType;
typedef struct Node
{
DataType data;
struct Node *next;
} Node;

单链表的实现

函数声明

/* 函数声明 */

//	1)、初始化单链表
Node *initList();
//	2)、建立单链表
Node *creatList(DataType arr[], int n);
//	3)、销毁单链表
void destroy(Node *first);
//	4)、判空操作
int isEmpty(Node *first);
//	5)、求单链表的长度
int getLength(Node *first);
//	6)、遍历操作
void printList(Node *first);
//	7)、按值查找
int locate(Node *first, DataType n);
//	8)、按位查找
/*
L:单链表的指针
i:需要查找第几个元素
ptr:存储查找到的元素
*/
int get(Node *first, DataType i, DataType *ptr);
//	9)、插入操作
/*
L:单链表的指针
i:需要插入到第几个元素
x:插入元素的值
*/
int insert(Node *first, DataType i, DataType x);
// 10)、按位删除
/*
L:单链表指针
i:需要删除第几个元素
ptr:存储删除的元素
*/
int deleteByPosition(Node *first, DataType i, DataType *ptr);

测试

/* 测试 */
int main()
{
int arr[] = {1,2,3,4,5};
Node *first = NULL;
first = creatList(arr, 5);

printf("单链表的长度:%d\n", getLength(first));

printf("遍历单链表:");
printList(first);
printf("\n");

int x,flag;
printf("请输入要查找的元素:");
scanf("%d", &x);
flag = locate(first, x);
if(flag)
printf("查找成功,序号为%d\n", flag);
else
printf("查找失败\n");

int locatePos, y;
printf("请输入你要查找的位置:");
scanf("%d", &locatePos);
if(get(first, locatePos, &y))
printf("查找成功,第%d个元素为:%d\n", locatePos,y);

int insertPos, insertValue;
printf("请输入插入元素的位置:");
scanf("%d", &insertPos);
if(insert(first, insertPos, 33))
{
printf("插入成功,插入后遍历单链表:");
printList(first);
printf("\n");
}

int deletePos, z;
printf("请输入你要删除的位置:");
scanf("%d", &deletePos);
if(deleteByPosition(first, deletePos, &z))
{
printf("删除第%d个元素%d成功,删除后遍历单链表:\n", deletePos,z);
printList(first);
printf("\n");
}

destroy(first);

if(isEmpty(first))
{
printf("单链表已销毁");
}
}

函数定义

/* 函数定义 */

Node *initList()
{
Node *first = (Node *)malloc(sizeof(Node));
first->next = NULL;
return first;
}

//头插法创建单链表:每次新申请的节点插在头结点之后
Node *creatList(DataType arr[], int n)
{
Node *s = NULL;
Node *first = (Node *)malloc(sizeof(Node));
first->next = NULL;
for(int i = 0; i< n; i++)
{
s = (Node *)malloc(sizeof(Node));
s->data = arr[i];
s->next = first->next; first->next = s;
}
return first;
}

int isEmpty(Node *first)
{
if(first->next)
return 1;
else
return 0;
}

int getLength(Node *first)
{
Node *p = first->next;	//工作指针p初始化
int length = 0;
while(p != NULL)
{
p = p->next;
length++;
}
return length;
}

void printList(Node *first)
{
Node *p = first->next;
while(p != NULL)
{
printf("%d\t", p->data);
p = p->next;
}
}

int locate(Node *first, DataType n)
{
int flag = 0;
Node *p = first->next;
while(p != NULL)
{
if(p->data == n)
{
return flag+1;
}
p = p->next;
flag++;
}
return 0;
}

int get(Node *first, DataType i, DataType *ptr)
{
Node *p = first->next;
int count = 1;
while(p != NULL && count < i)
{
p = p->next;
count++;
}
if(p == NULL)
{
printf("位置错误,查找失败\n");
return 0;
}
else
{
*ptr = p->data;
return 1;
}
}

int insert(Node *first, DataType i, DataType x)
{
Node *p = first;
Node *s = NULL;
int count = 0;
while(p != NULL && count < i-1)
{
p = p->next;
count++;
}
if(p == NULL)
{
printf("位置错误,插入失败\n");
return 0;
}
else
{
s = (Node *)malloc(sizeof(Node));
s->data = x;
s->next = p->next; p->next = s;
return 1;
}
}

int deleteByPosition(Node *first, DataType i, DataType *ptr)
{
Node *p = first;
Node *q = NULL;
int count = 0;
while(p != NULL && count < i-1)
{
p = p->next;
count++;
}
if(p == NULL || p->next == NULL)
{
printf("位置错误,删除失败\n");
return 0;
}
else
{
q = p->next; p->next = q->next;
*ptr = q->data;
free(q);
return 1;
}
}

void destroy(Node *first)
{
Node *p = first;
while(first != NULL)
{
first = first->next;
free(p);
p = first;
}
}

运行效果



(三)顺序表和链表的比较

时间性能比较

访问元素优势——顺序表:
取出线性表的第i个元素这种操作,使用顺序表更快一些,其时间复杂度为O(1);单链表的时间复杂度为O(n),因为它只能从表头开始依次向后扫描。

插入、删除元素优势——链表:
在链表总插入和删除元素不需要移动元素,其时间复杂度为O(1);在顺序表中插入和删除操作需要移动元素,其平均时间复杂度为O(n),当元素较多时,移动元素的时间开销很大。

一般规律:

​ 若线性表需频繁查找却很少进行插入和删除操作,或者操作和“数据元素在线性表中的位置“密切相关时,宜采用顺序表作为存储结构;反之,宜采用链表作为存储结构。

空间性能比较

链表中需要指针的结构性开销

顺序表存储长度需要事先固定,而链表无此限制

一般规律:

​ 当线性表中的元素个数变化较大或者未知时,最好使用链表实现;如果事先已知线性表的大致长度,使用顺性表的空间效率会更高。

结语

注:运行代码需要补上头文件

学习博客:结构体 :http://blog.csdn.net/ly666888555/article/details/52206973

参考书籍:《数据结构——从概念到C实现》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息