线性表的特点
线性结构的特定是:在数据的非空有限集中
- 存在唯一的一个被称做第一个的数据元素
- 存在唯一的一个被称为最后一个的数据元素
- 除了第一个外,集合中所有数据元素都由一个前驱
- 除了最后一个外,集合中所有的元素都有一个后继
线性表的顺序表示和实现
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1 // 英文翻译,不可行,不可能
#define OVERFLOW -2 // 英文翻译,溢出
typedef int Status;
typedef int ElemType;
// #define ElemType int
#define LIST_INIT_SIZE 5 // 线性表初始分配量
#define LISTINCREMENT 10 // 增量
typedef struct {
ElemType * elem; // 线性表基地址
int length; // 列表长度
int listsize; // 当前分配存储容量(以sizeof(ElemType)为单位)
} SqList;
Status InitList_Sq(SqList *L) { // 创建一个线性表
(*L).elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!(*L).elem) { // 存储分配失败
printf("创建失败\n");
exit(OVERFLOW);
}
(*L).length = 0; // 初始长度
(*L).listsize = LIST_INIT_SIZE; // 初始存储容量
printf("创建成功\n");
return OK;
}
Status ListInsert_Sq(SqList *L, int i, ElemType e) {
if (i < 1 || i > (*L).length + 1) {
printf("插入失败\n");
return ERROR;
}
if ((*L).length >= (*L).listsize) { // 存储空间已满,分配新内存
ElemType * newbase = (ElemType *)realloc((*L).elem, ((*L).listsize + LISTINCREMENT) * sizeof(ElemType));
if (!newbase) {
exit(OVERFLOW);
}
(*L).elem = newbase;
(*L).listsize += LISTINCREMENT;
}
ElemType *q = &((*L).elem[i - 1]);
printf("%p\n", q);
for (ElemType *p = &((*L).elem[(*L).length - 1]); p >= q; p--) {
// 插入位置及之后的元素右移
*(p+1) = *p;
}
*q = e;
++(*L).length;
printf("插入成功\n");
return OK;
}
Status ListDelete_Sq(SqList *L, int i, ElemType *e) {
// 假设原有2位[1,3] i = 1;
// *p 指向第一个元素
// 通过指针给e赋值,相当于将被删除的元素值返回
// *q 指向最后一个元素
// 首先++p,现在p指向最后一个元素
// p <= q,p和q相等,将值左移一位
// p++ 后,指针出界,p > q, 不满足条件
if (i < 1 || i > (*L).length + 1) {
printf("删除失败\n");
return ERROR;
}
ElemType *p = &((*L).elem[i - 1]);
*e = *p;
ElemType *q = (*L).elem + (*L).length; // 指向最后一个元素 相当于 [] + length
for (++p; p <= q; ++p) {
*(p - 1) = *p;
}
--(*L).length;
printf("删除成功\n");
return OK;
}
int LocateElem_Sq(SqList *L, ElemType e, Status (* compare)(ElemType, ElemType)) {
int i = 1;
ElemType *p = (*L).elem;
while(i <= (*L).length && !(* compare)(*p++, e)) {
++i;
}
if (i <= (*L).length) {
return i;
}
return 0;
}
Status compare(ElemType x, ElemType y) {
printf("%d,%d\n", x, y);
return x == y ? TRUE : FALSE;
}
Status DestroyList(SqList *L) {
free((*L).elem);
(*L).elem = NULL;
printf("线性表被释放!表长度:%d\n", L->length);
printf("线性表被释放!表空间:%lu字节\n", L->listsize * sizeof(ElemType));
L->length = 0;
L->listsize = 0;
return OK;
}
int ListLength(SqList *L) {
return (*L).length;
}
Status ListEmpty(SqList *L) {
if ((*L).elem == NULL) {
return TRUE;
}
return FALSE;
}
Status ClearList(SqList *L) {
if ((*L).elem != NULL) {
free((*L).elem);
(*L).elem = NULL;
}
(*L).elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
if (!(*L).elem) { // 存储分配失败
printf("重置为空表\n");
exit(OVERFLOW);
}
L->length = 0;
L->listsize = LIST_INIT_SIZE;
return OK;
}
int main(){
Status InitList_Sq(SqList *L);
Status ListInsert_Sq(SqList *L, int i, ElemType e);
Status ListDelete_Sq(SqList *L, int i, ElemType *e);
Status compare(ElemType x, ElemType y);
int LocateElem_Sq(SqList *L, ElemType e, Status (* compare)(ElemType, ElemType));
Status DestroyList(SqList *L);
SqList *list;
// 创建线性表
InitList_Sq(list);
printf("length=%d\n", (*list).length);
// 数据插入线性表
ListInsert_Sq(list, (*list).length + 1, 1990);
ListInsert_Sq(list, (*list).length + 1, 1991);
ListInsert_Sq(list, (*list).length + 1, 1991);
ListInsert_Sq(list, (*list).length + 1, 1991);
ListInsert_Sq(list, (*list).length + 1, 1991);
ListInsert_Sq(list, (*list).length + 1, 1991);
ListInsert_Sq(list, (*list).length + 1, 1991);
ListInsert_Sq(list, (*list).length + 1, 1991);
printf("length=%d\n", (*list).length);
// 删除线性表的数据
ElemType e;
ListDelete_Sq(list, 2, &e);
// printf("e=%d\n", e);
printf("listsize=%d\n", (*list).listsize);
e = 1991;
int index = LocateElem_Sq(list, e, *compare);
printf("index=%d\n", index);
DestroyList(list);
printf("ListEmpty=%d\n", ListEmpty(list));
printf("ClearList=%d\n", ClearList(list));
return 0;
}
线性链表的实现
指针型
#include <stdlib.h>
#include <stdio.h>
typedef int Status;
typedef int ElemType;
typedef struct LNode {
ElemType data;
int length;
struct LNode *next;
}LNode, *LinkList;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1 // 英文翻译,不可行,不可能
#define OVERFLOW -2 // 英文翻译,溢出
Status CreateList_L(LinkList *L, int n) {
(*L) = (LinkList)malloc(sizeof(LNode));
(*L) -> next = NULL;
(*L) -> length = 0;
int i;
LinkList q;
for (i = n; i > 0; --i) {
LinkList p = (LinkList)malloc(sizeof(LNode));
printf("请输入数据:");
scanf("%d", &p -> data);
if ((*L) -> next == NULL) {
p -> next = (*L) -> next;
(*L) -> next = p;
q = p;
(*L) -> length += 1;
} else {
q -> next = p;
p -> next = NULL;
q = p;
(*L) -> length += 1;
}
}
return OK;
}
ElemType *GetElem_L(LinkList L, int i) {
LinkList p = L -> next;
int j = 1;
while(p && j < i) {
p = p -> next;
++j;
}
if (!p || j > i) {
return ERROR;
}
return &(p -> data);
}
void printAll(LinkList L) {
LinkList p = L -> next;
int i = 1;
while(p != NULL) {
printf("item[%d]=%d\n",i, p -> data);
i++;
p = p -> next;
}
}
Status ListInsert_L(LinkList L, int i, ElemType e) {
LinkList p = L -> next;
int j = 0;
while (p && j < i - 1) {
p = p -> next;
++j;
}
if (!p || j > i - 1) {
return ERROR;
}
LinkList s = (LinkList)malloc(sizeof(LNode));
s -> data = e;
s -> next = p -> next;
p -> next = s;
L -> length += 1;
return OK;
}
Status ListDelete_L(LinkList L, int i, ElemType *e) {
LinkList p = L -> next;
int j = 1;
while (p && j < i - 1) {
p = p -> next;
++j;
}
if (!(p -> next) || j > i - 1) {
return ERROR;
}
LinkList q = p -> next; // p = 要被删除的那个的前一个
p -> next = q -> next;
*e = q -> data;
L -> length -= 1;
free(q);
return OK;
}
int main(){
Status CreateList_L(LinkList *L, int n);
ElemType *GetElem_L(LinkList L, int i);
LinkList list;
CreateList_L(&list, 2);
printf("item=%d\n", *GetElem_L(list, 1));
printf("item=%d\n", *GetElem_L(list, 2));
printf("length=%d\n", (*list).length);
ListInsert_L(list, (*list).length, 18);
printAll(list);
ElemType e;
printf("length=%d\n", (*list).length);
ListDelete_L(list, (*list).length, &e);
printf("e=%d\n", e);
printAll(list);
return 0;
}
静态链表(用数组来表示的)
以i代替动态指针p,类似与 p = p -> next
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
typedef int ElemType;
#define format_elem "%d"
typedef struct {
ElemType data;
int cur; // 存储下标
} component, SLinkList[MAXSIZE];
void InitSpace_SL(SLinkList *S) { // 初始化
int i = 0;
for (i = 0; i < MAXSIZE - 1; ++i) {
S[i] -> cur = i + 1;
}
S[MAXSIZE - 1]-> cur = 0;
}
int Malloc_SL(SLinkList *S) { // 分配空间
int i = S[0]-> cur;
if (S[0]-> cur) {
S[0]-> cur = S[i]-> cur;
}
return i;
}
void Free_SL(SLinkList *S, int k) { // 释放空间
}
void printAll(SLinkList *S, int r) {
S[0]-> cur = S[r] -> cur;
while(S[0] -> cur != 0) {
printf("item[%d]=%d\n", r, S[r] -> data);
r = S[r] -> cur; // 指针下移
S[0] -> cur = r; // 指针下移
}
}
int main() {
SLinkList list;
InitSpace_SL(&list); // 初始化
int i = Malloc_SL(&list); // 获取头指针位置 i = 1
int r = i; // r 是头指针
(&list)[i] -> data = 11; // (&list)[i] -> cur = 2
i = Malloc_SL(&list); // 指针后移 i = 2
(&list)[i] -> data = 22; // (&list)[i] -> cur = 3
(&list)[i] -> cur = 0; // (&list)[i] -> cur = 0
printAll(&list, r);
}
循环链表
循环链表和指针型链表表现一致,只是最后一个节点不的next不指向NULL,而是指向头指针
双向链表
typedef struct DcLNode {
ElemType data;
struct DuLNode *prior; // 指向上一个节点
struct DuLNode *next; // 指向下一个节点
}
d = d -> next -> prior = d -> prior - next;