线性表的特点
线性结构的特定是:在数据的非空有限集中
- 存在唯一的一个被称做第一个的数据元素
- 存在唯一的一个被称为最后一个的数据元素
- 除了第一个外,集合中所有数据元素都由一个前驱
- 除了最后一个外,集合中所有的元素都有一个后继
线性表的顺序表示和实现
#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; // 指向最后一个元素 相当于 [] + lengthfor (++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 10typedef 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 = 1int r = i; // r 是头指针(&list)[i] -> data = 11; // (&list)[i] -> cur = 2i = Malloc_SL(&list); // 指针后移 i = 2(&list)[i] -> data = 22; // (&list)[i] -> cur = 3(&list)[i] -> cur = 0; // (&list)[i] -> cur = 0printAll(&list, r);}
循环链表
循环链表和指针型链表表现一致,只是最后一个节点不的next不指向NULL,而是指向头指针
双向链表
typedef struct DcLNode {ElemType data;struct DuLNode *prior; // 指向上一个节点struct DuLNode *next; // 指向下一个节点}d = d -> next -> prior = d -> prior - next;
