《大话数据结构》—— 线性表
1.时间复杂度效率
O(1) > O(logn) > O(n) > O(nlogn) > O(n^2) > O(n^3) > O(2^n) > O(n!) > O(n^n)
2.线性表
2.1线性表——顺序存储
// 线性表----顺序存储
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 1024
typedef int ElementType;
typedef struct
{
ElementType data[MAXSIZE]; // 数组存储数据元素
int length; // 当前线性表长度
}SqList;
SqList * InitList(SqList * L); // 初始化线性表(空表)
int GetElem(SqList * L, int i, ElementType * e); // 获取线性表L第i个元素给e
int ListInsert(SqList * L, int i, ElementType e); // 插入元素
int ListDelete(SqList * L, int i, ElementType * e); // 删除元素
int PrintList(SqList * L); // 遍历线性表
int ClearList(SqList * L); // 清空线性表
int DestoryList(SqList * L); // 销毁线性表
int main()
{
SqList * L = NULL;
L = InitList(L);
if (L!=NULL) {
printf("初始化线性表(空表)成功\n");
}
ListInsert(L, 1, 999);
ListInsert(L, 2, 888);
ListInsert(L, 3, 777);
PrintList(L);
printf("\n清空线性表...\n");
ClearList(L);
PrintList(L);
}
// 初始化顺序表(空表)
SqList * InitList(SqList * L)
{
L = (SqList *)malloc(sizeof(SqList));
if (L!=NULL) {
L->length = 0;
}
return L;
}
// 获取线性表L第i个元素给e
int GetElem(SqList * L, int i, ElementType *e)
{
if (L->length == 0 || i<i || i>L->length) {
return 0;
}
*e = L->data[i-1];
return 1;
}
// 插入元素
int ListInsert(SqList * L, int i, ElementType e)
{
if (L->length == MAXSIZE) { // 判断线性表是否已满
return 0;
}
if (i<1 || i>L->length + 1) {
return 0;
}
if (i<=L->length) {
for (int k = L->length - 1; k>=i-1; k--) {
L->data[k+1] = L->data[k];
}
}
L->data[i-1] = e;
L->length++;
return 1;
}
// 删除元素
int ListDelete(SqList * L, int i, ElementType *e)
{
if (L->length == 0) {
return 0;
}
if (i<1 || i>L->length) {
return 0;
}
*e = L->data[i-1];
if (i<L->length) {
for (int k = i; k<L->length;k++) {
L->data[k-1] = L->data[k];
}
}
L->length--;
return 1;
}
// 遍历线性表
int PrintList(SqList * L)
{
if (L->length == 0) {
printf("线性表为空!\n");
}
for (int i = 0; i< L->length; i++) {
printf("a[%d]=%d\t", i, L->data[i]);
if ((i + 1) % 5 == 0) {
printf("\n");
}
}
return 1;
}
// 清空线性表
int ClearList(SqList * L)
{
L->length = 0;
return 1;
}
// 销毁线性表
int DestoryList(SqList * L)
{
free(L);
return 1;
}
2.2线性表——链式存储结构
// 线性表----链式存储
#include <stdio.h>
#include <stdlib.h>
typedef int ElementType;
typedef struct Node
{
ElementType data;
struct Node * next;
} Node;
typedef struct Node * LinkList;
// LinkList = struct Node *
// LinkList * L : 二级指针,L为struct Node ** 类型,只能存放struct Node *类型变量的地址
void CreateListHead(LinkList * L, int n); // 头插法建立单链表
void CreateListTail(LinkList * L, int n); // 尾插法建立单链表
int ListInsert(LinkList * L, int i, ElementType e); // 插入元素
int ListDelete(LinkList * L, int i, ElementType * e); // 删除元素
int GetElem(LinkList L, int i, ElementType * e); // 获取元素
int PrintList(LinkList L); // 遍历单链表
int ClearList(LinkList * L); // 整表删除
int main()
{
LinkList L; // = struct Node * L
CreateListTail(&L, 10); // &L:struct node * 类型的地址
PrintList(L);
ListInsert(&L, 2, 666);
PrintList(L);
ClearList(&L);
PrintList(L);
}
// 头插法建立单链表
void CreateListHead(LinkList * L, int n)
{
LinkList p;
*L = (LinkList)malloc(sizeof(Node));
(*L)->next = NULL;
for (int i = 0; i<n; i++)
{
p = (LinkList)malloc(sizeof(Node));
p->data = i;
p->next = (*L)->next;
(*L)->next = p;
}
}
// 尾插法建立单链表
void CreateListTail(LinkList * L, int n)
{
LinkList p, r;
*L = (LinkList)malloc(sizeof(Node));
r = *L; // r指向尾部的结点
for (int i = 0; i<n; i++)
{
p = (LinkList)malloc(sizeof(Node));
p->data = i;
r->next = p; // 表尾结点指向新结点
r = p; // 新节点为尾部结点r
}
r->next = NULL;
}
// 插入元素
int ListInsert(LinkList * L, int i, ElementType e)
{
int j;
LinkList p, s;
p = *L;
j = 1;
while (p && j<i) {
p = p->next;
++j;
}
if (!p || j>i) {
return 0;
}
s = (LinkList)malloc(sizeof(Node));
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}
// 删除元素
int ListDelete(LinkList * L, int i, ElementType * e)
{
int j;
LinkList p, q;
p = *L;
j = 1;
while (p->next && j<i) {
p = p->next;
++j;
}
if (!p || j>i) {
return 0;
}
q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return 1;
}
// 获取元素
int GetElem(LinkList L, int i, ElementType * e)
{
int j;
LinkList p; // 声明一指针p
p = L->next; // p指向L的第一个结点
j = 1; // j为计数器
while (p && j<i) {
p = p->next;
++j;
}
if (!p || j>i) {
return 0;
}
*e = p->data;
return 1;
}
// 遍历单链表
int PrintList(LinkList L)
{
LinkList p;
p = L->next;
if (p == NULL) {
printf("该链表为空!");
}
while (p !=NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
return 1;
}
// 整表删除
int ClearList(LinkList * L)
{
LinkList p, q;
p = (*L)->next; // p指向第一个结点
while(p) {
q = p->next;
free(p);
p = q;
}
(*L)->next = NULL; // 头结点指针域为空
return 1;
}
顺序存储和单链表对比
存储分配方式
- 顺序存储采用一段连续的存储单元一次存储线性表的数据元素
- 单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素
时间性能
- 查找:顺序存储结构O(1)、单链表O(n)
- 插入和删除:顺序存储结构需要平均移动表长一半的元素,时间为O(n)、单链表在找出某位置指针后,插入和查询仅为O(1)
空间性能
- 顺序存储结构需要预先分配空间、单链表不需要预先分配存储空间
2.3静态链表
..