高一凡-数据结构第2章-线性表

  • 2.2.1线性表的顺序表示和实现
    • 1.初始化
    • 2.销毁与清空
    • 3.判空与长度
    • 4.获取元素值与位置
  • 2.2.2换一种写法
  • 2.2.3归并
  • 2.3.1线性表的链式表示和实现
  • 2.3.2 不设头节点
  • 2.3.3 静态链
  • 2.3.4链表归并
  • 2.3.5循环链表
  • 2.3.6静态链表的操做
  • 2.7双向链表

2.2.1线性表的顺序表示和实现

结构体如下:

struct Sqlist
{ElemType *elem;int length;int listsize;
};

指针域是一个类型指针,用于顺序存储数据,两个标志位,length标志表当前存储数据个数,listsize标志表可容纳的数据量。

函数列表
void InitList(Sqlist &L); --初始化
void DestoryList(Sqlist &L);–销毁
void ClearList(Sqlist &L);–清空
Status ListEmpty(Sqlist L);–表空为真
int ListLength(Sqlist L);–返回表长
Status GetElem(Sqlist L, int i, ElemType &e);–获取表中元素值
int LocateElem(Sqlist L, ElemType e, Status(*compare)
Status PriorElem(Sqlist L, ElemType cur_e, ElemType &pre_e);找前驱元素
Status NextElem(Sqlist L, ElemType cur_e, ElemType &next_e);找后继元素
Status ListInsert(Sqlist &L, int i, ElemType e);插入
Status ListDelete(Sqlist &L, int i, ElemType &e);删除
void ListTraverse(Sqlist &L, void(*visit)(ElemType&));遍历
Status equal(ElemType c1, ElemType c2);附加函数,判等
int comp(ElemType a, ElemType b);比较
void print(ElemType c);打印
void print1(ElemType &c);
void print2(ElemType c);

1.初始化

传入引用型顺序表结构L,对于L的指针域进行分配最大顺序空间,同时初始化L的数据长度,以及顺序表的可用长度。

void InitList(Sqlist &L)
{L.elem = (ElemType*)malloc(sizeof(ElemType) * LIST_INIT_SIZE);if (!L.elem)exit(OVERFLOW);L.length = 0;L.listsize = LIST_INIT_SIZE;
}

2.销毁与清空

销毁即free掉分配给L指针域的空间,传入的是引用。

void DestoryList(Sqlist &L)
{free(L.elem);L.elem = NULL;L.length = 0;L.listsize = 0;
}

清空就比较简单,直接将L的当前长度置为0,再次使用时,会覆盖掉原来的值。

void ClearList(Sqlist &L)
{L.length = 0;
}

3.判空与长度

判定条件,L的当前长度为0

Status ListEmpty(Sqlist L)
{if (L.length == 0)return TRUE;elsereturn FALSE;
}int ListLength(Sqlist L)
{return L.length;
}

4.获取元素值与位置

Status GetElem(Sqlist L, int i, ElemType &e)
{if (i<1 || i>L.length)return ERROR;e = *(L.elem + i - 1);//注意这里是i-1,数据从*elem开始return OK;
}

//这里的compare可以看成equal函数,当二者相等时判1,否则判0。

int LocateElem(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;elsereturn 0;
}

//寻找前一个节点

Status PriorElem(Sqlist L, ElemType cur_e, ElemType &pre_e)
{int i = 1;ElemType *p = L.elem + 1;while (i <= L.length &&*p != cur_e){p++;i++;}if (i > L.length)return ERROR;else{pre_e = *--p;return OK;}
}

//寻找后一个结点

Status NextElem(Sqlist L, ElemType cur_e, ElemType &next_e)
{int i = 1;ElemType *p = L.elem;while (i < L.length && *p != cur_e){p++;i++;}if (i == L.length)return ERROR;else{next_e = *++p;return OK;}
}

Status ListInsert(Sqlist &L, int i, ElemType e)
{ElemType *newbase, *p, *q;if (i < 1 || i >L.length + 1)return ERROR;if (L.length == L.listsize){newbase = (ElemType*)realloc(L.elem, (L.listsize + LIST_INCREMENT) * sizeof(ElemType));if (!newbase)exit(OVERFLOW);L.elem = newbase;L.listsize += LIST_INCREMENT;}q = L.elem + i - 1;for (p = L.elem + L.length - 1; p >= q; --p)*(p + 1) = *p;*q = e;++L.length;return OK;
}

Status ListDelete(Sqlist &L, int i, ElemType &e)
{ElemType *p, *q;if (i<1 || i>L.length)return ERROR;p = L.elem + i - 1;e = *p;q = L.elem + L.length - 1;for (++p; p <= q; ++p)*(p - 1) = *p;L.length--;return OK;
}
void ListTraverse(Sqlist &L, void(*visit)(ElemType&))
{ElemType *p = L.elem;int i;for (i = 1; i <= L.length; i++)visit(*p++);printf("\n");
}

实现文件2:func2-2.cpp

#include"C1.H"
Status equal(ElemType c1, ElemType c2)
{if (c1 == c2)return TRUE;elsereturn FALSE;
}int comp(ElemType a, ElemType b)
{if (a == b)return 0;elsereturn (a - b) / abs(a - b);
}void print(ElemType c)
{printf("%d", c);
}void print1(ElemType &c)
{printf("%d ", c);
}void print2(ElemType c)
{printf("%c", c);
}

主函数

#include "C1.H"Status sq(ElemType c1, ElemType c2)
{if (c1 == c2 * c2)return TRUE;elsereturn FALSE;
}void dbl(ElemType &c)
{c *= 2;
}int main()
{Sqlist L;ElemType e, e0;Status i;int j, k;InitList(L);printf("初始化L后,L.length = %d,L.listsize = %d,L.elem = %u\n", L.length, L.listsize, L.elem);for (j = 1; j <= 5; j++)i = ListInsert(L, 1, j);printf("在L的表头插入1-5之后,*L.elem = ");for (j = 1; j <= 5; j++)printf("%d ", *(L.elem + j - 1));printf("\n调用ListTraverse()函数,依次输出表L中的元素:");ListTraverse(L, print1);i = ListEmpty(L);printf("L.length = %d,L.listsize = %d,", L.length, L.listsize);printf("L.elem = %u,L是否为空?i = %d\n\n", L.elem, i);ClearList(L);i = ListEmpty(L);printf("L.length = %d,L.listsize = %d,", L.length, L.listsize);printf("L.elem = %u,L是否为空?i = %d,", L.elem, i);for (j = 1; j <= 10; j++)ListInsert(L, j, j);printf("在标为插入1-10之后,L = ");ListTraverse(L, print1);printf("L.length = %d,L.listsize = %d,L.elem = %u\n", L.length, L.listsize, L.elem);ListInsert(L, 1, 0);printf("在L的表头插入0后,L.length = %d,L.listsize = %d,L.elem = %u\n ", L.length, L.listsize, L.elem);GetElem(L, 5, e);ListTraverse(L, print1);printf("第5个元素值为 %d ", e);for (j = 10; j <= 11; j++){k = LocateElem(L, j, equal);if (k)printf("第 %d 个元素的值为 %d\n", k, j);elseprintf("没有值为 %d 的元素\n", j);}for (j = 3; j <= 4; j++){k = LocateElem(L, j, sq);if (k)printf("第 %d 个元素的值为 %d 的平方\n", k, j);elseprintf("没有值为 %d 的平方的元素\n", j);}for (j = 1; j <= 2; j++){GetElem(L, j, e0);i = PriorElem(L, e0, e);if (i == ERROR)printf("元素%d无前驱\n", e0);elseprintf("元素%d的前驱为%d\n", e0, e);}for (j = ListLength(L) - 1; j <= ListLength(L); j++){GetElem(L, j, e0);i = NextElem(L, e0, e);if (i == ERROR)printf("元素%d无后继\n", e0);elseprintf("元素%d的后继为%d\n", e0, e);}k = ListLength(L);for ( j = k+1; j >= k; j--){i = ListDelete(L, j, e);if (i == ERROR)printf("%d个元素删除失败\n", j);elseprintf("%d个元素删除成功,值为%d\n", j, e);}ListTraverse(L,dbl);printf("L的元素加倍后L = ");ListTraverse(L, print1);DestoryList(L);printf("销毁L后,L.length = %d,L.listsize = %d,L.elem = %u\n", L.length, L.listsize, L.elem);return 0;
}

2.2.2换一种写法

头文件c1.h

// c1.h (文件名)
#ifndef C1_H
#define C1_H#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2#include<string.h> // 字符串函数头文件
#include<ctype.h> // 字符函数头文件
#include<malloc.h> // malloc()等
#include<limits.h> // INT_MAX等
#include<stdio.h> // 标准输入输出头文件,包括EOF(=^Z或F6),NULL等
#include<stdlib.h> // atoi(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
// #define INFEASIBLE -1 没使用
// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE,第7、8章用到
typedef int ElemType;struct LNode
{ElemType data;LNode *next;
};
typedef LNode *LinkList;void InitList(LinkList &L);
void DestoryList(LinkList &L);
void ClearList(LinkList &L);
Status ListEmpty(LinkList L);int ListLength(LinkList L);Status GetElem(LinkList L, int i, ElemType &e);int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));
//寻找前一个节点
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e);
//寻找后一个结点
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e);Status ListInsert(LinkList &L, int i, ElemType e);
Status ListDelete(LinkList &L, int i, ElemType &e);void ListTraverse(LinkList &L, void(*visit)(ElemType));Status equal(ElemType c1, ElemType c2);
int comp(ElemType a, ElemType b);void print(ElemType c);
#endif

实现文件1func2-2.cpp

 // func2-2.cpp 几个常用的函数
#include"C1.H"Status equal(ElemType c1,ElemType c2){ // 判断是否相等的函数if(c1==c2)return TRUE;elsereturn FALSE;}int comp(ElemType a,ElemType b){ // 根据a<、=或>b,分别返回-1、0或1if(a==b)return 0;elsereturn (a-b)/abs(a-b);}void print(ElemType c){ // 以十进制整型的格式输出元素的值printf("%d ",c);}void print1(ElemType &c){ // 以十进制整型的格式输出元素的值(设c为引用类型)printf("%d ",c);}void print2(ElemType c){ // 以字符型的格式输出元素的值printf("%c ",c);}

实现文件2:bo2-2.cpp

#include"C1.H"void InitList(LinkList &L)
{L = (LNode*)malloc(sizeof(LNode));if (!L)exit(OVERFLOW);L->next = NULL;
}void DestoryList(LinkList &L)
{LinkList q;while (L){q = L->next;free(L);L = q;}}
void ClearList(LinkList &L)
{LinkList p = L->next;L->next = NULL;DestoryList(p);
}Status ListEmpty(LinkList L)
{if (L->next)return FALSE;elsereturn TRUE;
}int ListLength(LinkList L)
{int i = 0;LinkList q = L->next;while (q){i++;q = q->next;}return i;
}Status GetElem(LinkList L, int i, ElemType &e)
{int j = 1;LinkList q = L->next;while (q && j < i){j++;q = q->next;}if (!q || j > i)return ERROR;e = q->data;return OK;
}int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{int i = 0;LinkList p = L->next;while (p){i++;if (compare(p->data, e))return i;p = p->next;}return 0;
}
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e)
{LinkList q, p = L->next;while (p->next){q = p->next;if (q->data == cur_e){pre_e = p->data;return OK;}p = q;}return ERROR;
}Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{LinkList p = L->next;while (p->next){if (p->data == cur_e){next_e = p->next->data;return OK;}p = p->next;}return ERROR;
}Status ListInsert(LinkList &L, int i, ElemType e)
{int j = 0;LinkList s, p = L;while (p &&j < i - 1){j++;p = p->next;}if (!p || j > i - 1)return ERROR;s = (LinkList)malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;return OK;
}Status ListDelete(LinkList &L, int i, ElemType &e)
{int j = 0;LinkList q, p = L;while (p->next&&j < i - 1){j++;p = p->next;}if (!p->next || j > i - 1)return ERROR;q = p->next;p->next = q->next;e = q->data;free(q);return OK;
}void ListTraverse(LinkList &L, void(*visit)(ElemType))
{LinkList p = L->next;while (p){visit(p->data);p = p->next;}printf("\n");
}

主函数

 // algo2-3.cpp 实现算法2.11和2.12的程序#include"c1.h"void CreateList(LinkList &L,int n) // 算法2.11{ // 逆位序(结点插在表头)输入n个元素的值,建立带表头结点的单链线性表Lint i;LinkList p;L=(LinkList)malloc(sizeof(LNode)); // 生成头结点L->next=NULL; // 先建立一个带头结点的空单链表printf("请输入%d个数据\n",n);for(i=n;i>0;--i){ p=(LinkList)malloc(sizeof(LNode)); // 生成新结点scanf("%d",&p->data); // 给新结点输入元素值p->next=L->next; // 将新结点插在表头L->next=p; // 头结点指向新结点}}void CreateList1(LinkList &L,int n){ // 正位序(结点插在表尾)输入n个元素的值,建立带表头结点的单链线性表Lint i;LinkList p,q;L=(LinkList)malloc(sizeof(LNode)); // 生成头结点L->next=NULL; // 先建立一个带头结点的空单链表q=L; // q指向空表的头结点(相当于尾结点)printf("请输入%d个数据\n",n);for(i=1;i<=n;i++){ p=(LinkList)malloc(sizeof(LNode)); // 生成新结点scanf("%d",&p->data); // 给新结点输入元素值q->next=p; // 将新结点插在表尾q=q->next; // q指向尾结点}p->next=NULL; // 最后一个结点的指针域为空}void MergeList(LinkList La,LinkList &Lb,LinkList &Lc) // 算法2.12{ // 已知单链线性表La和Lb的元素按值非递减排列。// 归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列。(销毁Lb,Lc即新的La)LinkList pa=La->next,pb=Lb->next,pc; // pa、pb分别指向La、Lb的首元结点(待比较结点)Lc=pc=La; // 用La的头结点作为Lc的头结点,pc指向La的头结点(Lc的尾结点)while(pa&&pb) // La和Lb中的元素都未比较完if(pa->data<=pb->data) // La的当前元素不大于Lb的当前元素{ pc->next=pa; // 将pa所指结点归并到Lc中pc=pa; // pc指向表Lc的最后一个结点pa=pa->next; // 表La的下一个结点成为待比较结点}else // Lb的当前元素小于La的当前元素{ pc->next=pb; // 将pb所指结点归并到Lc中pc=pb; // pc指向表Lc的最后一个结点pb=pb->next; // 表Lb的下一个结点成为待比较结点}pc->next=pa?pa:pb; // 插入剩余段free(Lb); // 释放Lb的头结点Lb=NULL; // Lb不再指向任何结点}void main(){int n=5;LinkList La,Lb,Lc;printf("按非递减顺序,");CreateList1(La,n); // 根据输入顺序,正位序建立线性表printf("La="); ListTraverse(La,print); // 输出链表La的内容printf("按非递增顺序,");CreateList(Lb,n); // 根据输入顺序,逆位序建立线性表printf("Lb="); ListTraverse(Lb,print); // 输出链表Lb的内容MergeList(La,Lb,Lc); // 按非递减顺序归并La和Lb,得到新表Lcprintf("Lc="); ListTraverse(Lc,print); // 输出链表Lc的内容}

2.2.3归并

头文件

 // c1.h (文件名)
#ifndef C1_H
#define C1_H#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2#include<string.h> // 字符串函数头文件#include<ctype.h> // 字符函数头文件#include<malloc.h> // malloc()等#include<limits.h> // INT_MAX等#include<stdio.h> // 标准输入输出头文件,包括EOF(=^Z或F6),NULL等#include<stdlib.h> // atoi(),exit()#include<io.h> // eof()#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等#include<sys/timeb.h> // ftime()#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表// 函数结果状态代码。在教科书第10页#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0// #define INFEASIBLE -1 没使用// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE,第7、8章用到typedef int ElemType;struct Sqlist{ElemType *elem;int length;int listsize;};void InitList(Sqlist &L);void DestoryList(Sqlist &L);void ClearList(Sqlist &L);Status ListEmpty(Sqlist L);int ListLength(Sqlist L);Status GetElem(Sqlist L, int i, ElemType &e);int LocateElem(Sqlist L, ElemType e, Status(*compare)(ElemType, ElemType));//寻找前一个节点Status PriorElem(Sqlist L, ElemType cur_e, ElemType &pre_e);//寻找后一个结点Status NextElem(Sqlist L, ElemType cur_e, ElemType &next_e);Status ListInsert(Sqlist &L, int i, ElemType e);Status ListDelete(Sqlist &L, int i, ElemType &e);void ListTraverse(Sqlist &L, void(*visit)(ElemType&));Status equal(ElemType c1, ElemType c2);int comp(ElemType a, ElemType b);void print(ElemType c);void print1(ElemType &c);void print2(ElemType c);
#endif

bo2-1.cpp

#pragma once
#include"C1.H"
void InitList(Sqlist &L)
{L.elem = (ElemType*)malloc(sizeof(ElemType) * LIST_INIT_SIZE);if (!L.elem)exit(OVERFLOW);L.length = 0;L.listsize = LIST_INIT_SIZE;
}void DestoryList(Sqlist &L)
{free(L.elem);L.elem = NULL;L.length = 0;L.listsize = 0;
}void ClearList(Sqlist &L)
{L.length = 0;
}Status ListEmpty(Sqlist L)
{if (L.length == 0)return TRUE;elsereturn FALSE;
}int ListLength(Sqlist L)
{return L.length;
}Status GetElem(Sqlist L, int i, ElemType &e)
{if (i<1 || i>L.length)return ERROR;e = *(L.elem + i - 1);return OK;
}int LocateElem(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;elsereturn 0;
}
//寻找前一个节点
Status PriorElem(Sqlist L, ElemType cur_e, ElemType &pre_e)
{int i = 1;ElemType *p = L.elem + 1;while (i <= L.length &&*p != cur_e){p++;i++;}if (i > L.length)return ERROR;else{pre_e = *--p;return OK;}
}
//寻找后一个结点
Status NextElem(Sqlist L, ElemType cur_e, ElemType &next_e)
{int i = 1;ElemType *p = L.elem;while (i < L.length && *p != cur_e){p++;i++;}if (i == L.length)return ERROR;else{next_e = *++p;return OK;}
}Status ListInsert(Sqlist &L, int i, ElemType e)
{ElemType *newbase, *p, *q;if (i < 1 || i >L.length + 1)return ERROR;if (L.length == L.listsize){newbase = (ElemType*)realloc(L.elem, (L.listsize + LIST_INCREMENT) * sizeof(ElemType));if (!newbase)exit(OVERFLOW);L.elem = newbase;L.listsize += LIST_INCREMENT;}q = L.elem + i - 1;for (p = L.elem + L.length - 1; p >= q; --p)*(p + 1) = *p;*q = e;++L.length;return OK;
}Status ListDelete(Sqlist &L, int i, ElemType &e)
{ElemType *p, *q;if (i<1 || i>L.length)return ERROR;p = L.elem + i - 1;e = *p;q = L.elem + L.length - 1;for (++p; p <= q; ++p)*(p - 1) = *p;L.length--;return OK;
}void ListTraverse(Sqlist &L, void(*visit)(ElemType&))
{ElemType *p = L.elem;int i;for (i = 1; i <= L.length; i++)visit(*p++);printf("\n");
}

fun2-2.cpp

#include"C1.H"
Status equal(ElemType c1, ElemType c2)
{if (c1 == c2)return TRUE;elsereturn FALSE;
}int comp(ElemType a, ElemType b)
{if (a == b)return 0;elsereturn (a - b) / abs(a - b);
}void print(ElemType c)
{printf("%d", c);
}void print1(ElemType &c)
{printf("%d ", c);
}void print2(ElemType c)
{printf("%c", c);
}

主函数实现

#include"C1.H"void MergeList(Sqlist La, Sqlist Lb, Sqlist &Lc)
{ElemType *pa, *pa_last, *pb, *pb_last, *pc;pa = La.elem;pb = Lb.elem;Lc.length = Lc.listsize = La.length + Lb.length;pc = Lc.elem = (ElemType*)malloc(sizeof(ElemType) * Lc.length);if (!Lc.elem)exit(OVERFLOW);pa_last = pa + La.length - 1;pb_last = pb + Lb.length - 1;while (pa <= pa_last&&pb <= pb_last){if (*pa <= *pb)*pc++ = *pa++;else*pc++ = *pb++;}while (pa <= pa_last)*pc++ = *pa++;while (pb <= pb_last)*pc++ = *pb++;
}int main() {Sqlist La, Lb, Lc;int j;InitList(La);InitList(Lb);for (j = 1; j <= 5; j++)ListInsert(La, j, j);ListTraverse(La, print1);for (j = 1; j <= 5; j++)ListInsert(Lb, j, 2*j);ListTraverse(Lb, print1);MergeList(La, Lb, Lc);ListTraverse(Lc, print1);return 0;
}

2.3.1线性表的链式表示和实现

头文件

 // c1.h (文件名)
#ifndef C1_H
#define C1_H#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2#include<string.h> // 字符串函数头文件#include<ctype.h> // 字符函数头文件#include<malloc.h> // malloc()等#include<limits.h> // INT_MAX等#include<stdio.h> // 标准输入输出头文件,包括EOF(=^Z或F6),NULL等#include<stdlib.h> // atoi(),exit()#include<io.h> // eof()#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等#include<sys/timeb.h> // ftime()#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表// 函数结果状态代码。在教科书第10页#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0// #define INFEASIBLE -1 没使用// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE,第7、8章用到typedef int ElemType;struct LNode{ElemType data;LNode *next;};typedef LNode *LinkList;void InitList(LinkList &L);void DestoryList(LinkList &L);void ClearList(LinkList &L);Status ListEmpty(LinkList L);int ListLength(LinkList L);Status GetElem(LinkList L, int i, ElemType &e);int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));//寻找前一个节点Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e);//寻找后一个结点Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e);Status ListInsert(LinkList &L, int i, ElemType e);Status ListDelete(LinkList &L, int i, ElemType &e);void ListTraverse(LinkList &L, void(*visit)(ElemType));Status equal(ElemType c1, ElemType c2);int comp(ElemType a, ElemType b);void print(ElemType c);void print1(ElemType c);void print2(ElemType c);
#endif

实现函数:

#include"C1.H"void InitList(LinkList &L)
{L = (LNode*)malloc(sizeof(LNode));if (!L)exit(OVERFLOW);L->next = NULL;
}void DestoryList(LinkList &L)
{LinkList q;while (L){q = L->next;free(L);L = q;}}
void ClearList(LinkList &L)
{LinkList p = L->next;L->next = NULL;DestoryList(p);
}Status ListEmpty(LinkList L)
{if (L->next)return FALSE;elsereturn TRUE;
}int ListLength(LinkList L)
{int i = 0;LinkList q = L->next;while (q){i++;q = q->next;}return i;
}Status GetElem(LinkList L, int i, ElemType &e)
{int j = 1;LinkList q = L->next;while (q && j < i){j++;q = q->next;}if (!q || j > i)return ERROR;e = q->data;return OK;
}int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{int i = 0;LinkList p = L->next;while (p){i++;if (compare(p->data, e))return i;p = p->next;}return 0;
}
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e)
{LinkList q, p = L->next;while (p->next){q = p->next;if (q->data == cur_e){pre_e = p->data;return OK;}p = q;}return ERROR;
}Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{LinkList p = L->next;while (p->next){if (p->data == cur_e){next_e = p->next->data;return OK;}p = p->next;}return ERROR;
}Status ListInsert(LinkList &L, int i, ElemType e)
{int j = 0;LinkList s, p = L;while (p &&j < i - 1){j++;p = p->next;}if (!p || j > i - 1)return ERROR;s = (LinkList)malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;return OK;
}Status ListDelete(LinkList &L, int i, ElemType &e)
{int j = 0;LinkList q, p = L;while (p->next&&j < i - 1){j++;p = p->next;}if (!p->next || j > i - 1)return ERROR;q = p->next;p->next = q->next;e = q->data;free(q);return OK;
}void ListTraverse(LinkList &L, void(*visit)(ElemType))
{LinkList p = L->next;while (p){visit(p->data);p = p->next;}printf("\n");
}void print(ElemType c)
{printf("%d", c);
}

主函数

#include "C1.H"int main()
{LinkList L;ElemType e, e0;Status i;int j, k;InitList(L);for (j = 1; j <= 5; j++)i = ListInsert(L, 1, j);printf("在L的表头一次插入1-5后,L = ");ListTraverse(L, print);i = ListEmpty(L);printf("L是否空?i = %d(1是0否),表L的长度 = %d\n", i, ListLength(L));ClearList(L);printf("清空L之后,L = ");ListTraverse(L, print);i = ListEmpty(L);printf("L是否空?i = %d(1是0否),表L的长度 = %d\n", i, ListLength(L));for (j = 1; j <= 10; j++)i = ListInsert(L, j, j);for (j = 1; j <= 2; j++){GetElem(L, j, e0);i = PriorElem(L, e0, e);if (i == ERROR)printf("元素%d无前驱\n", e0);elseprintf("元素%d的前驱为%d\n", e0, e);}for (j = ListLength(L) - 1; j <= ListLength(L); j++){GetElem(L, j, e0);i = NextElem(L, e0, e);if (i == ERROR)printf("元素%d无后继\n", e0);elseprintf("元素%d的后继为%d\n", e0, e);}k = ListLength(L);for (j = k + 1; j >= k; j--){i = ListDelete(L, j, e);if (i == ERROR)printf("%d个元素删除失败\n", j);elseprintf("%d个元素删除成功,值为%d\n", j, e);}printf("依次输出L的元素:");ListTraverse(L, print);DestoryList(L);printf("销毁后,L = %u", L);
}

2.3.2 不设头节点

头文件

// c1.h (文件名)
#ifndef C1_H
#define C1_H#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2#include<string.h> // 字符串函数头文件
#include<ctype.h> // 字符函数头文件
#include<malloc.h> // malloc()等
#include<limits.h> // INT_MAX等
#include<stdio.h> // 标准输入输出头文件,包括EOF(=^Z或F6),NULL等
#include<stdlib.h> // atoi(),exit()
#include<io.h> // eof()
#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等
#include<sys/timeb.h> // ftime()
#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表
// 函数结果状态代码。在教科书第10页
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
// #define INFEASIBLE -1 没使用
// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行
typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE,第7、8章用到
typedef int ElemType;struct LNode
{ElemType data;LNode *next;
};
typedef LNode *LinkList;void InitList(LinkList &L);
void DestoryList(LinkList &L);
void ClearList(LinkList &L);
Status ListEmpty(LinkList L);int ListLength(LinkList L);Status GetElem(LinkList L, int i, ElemType &e);int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));
//寻找前一个节点
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e);
//寻找后一个结点
Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e);Status ListInsert(LinkList &L, int i, ElemType e);
Status ListDelete(LinkList &L, int i, ElemType &e);void ListTraverse(LinkList &L, void(*visit)(ElemType));Status equal(ElemType c1, ElemType c2);
int comp(ElemType a, ElemType b);void print(ElemType c);void Union(LinkList &La, LinkList Lb);
void MergeList(LinkList La, LinkList Lb, LinkList &Lc);
#endif
// bo2-3.cpp 不设头结点的单链表(存储结构由c2-2.h定义)的部分基本操作(9个)
#include"C1.h"
#define DestroyList ClearList // DestroyList()和ClearList()的操作是一样的
void InitList(LinkList &L)
{ // 操作结果:构造一个空的线性表LL = NULL; // 指针为空
}void ClearList(LinkList &L)
{ // 初始条件:线性表L已存在。操作结果:将L重置为空表LinkList p;while (L) // L不空{p = L; // p指向首元结点L = L->next; // L指向第2个结点(新首元结点)free(p); // 释放首元结点}
}Status ListEmpty(LinkList L)
{ // 初始条件:线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSEif (L)return FALSE;elsereturn TRUE;
}int ListLength(LinkList L)
{ // 初始条件:线性表L已存在。操作结果:返回L中数据元素的个数int i = 0; // 计数器初值为0LinkList p = L; // p指向第1个结点while (p) // p指向结点(未到表尾){i++; // 计数器+1p = p->next; // p指向下一个结点}return i;
}Status GetElem(LinkList L, int i, ElemType &e)
{ // L为不设头结点的单链表的头指针。当第i个元素存在时,其值赋给e并返回OK,// 否则返回ERRORint j = 1; // 计数器初值为1LinkList p = L; // p指向第1个结点if (i<1) // i值不合法return ERROR;while (j<i&&p) // 未到第i个元素,也未到表尾{j++; // 计数器+1p = p->next; // p指向下一个结点}if (j == i&&p) // 存在第i个元素{e = p->data; // 取第i个元素的值赋给ereturn OK; // 成功返回OK}return ERROR; // 不存在第i个元素,失败返回ERROR
}int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{ // 初始条件:线性表L已存在,compare()是数据元素判定函数(满足为1,否则为0)// 操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。//           若这样的数据元素不存在,则返回值为0int i = 0; // 计数器初值为0LinkList p = L; // p指向第1个结点while (p) // 未到表尾{i++; // 计数器+1if (compare(p->data, e)) // 找到这样的数据元素return i; // 返回其位序p = p->next; // p指向下一个结点}return 0; // 满足关系的数据元素不存在
}Status ListInsert(LinkList &L, int i, ElemType e)
{ // 在不设头结点的单链线性表L中第i个位置之前插入元素eint j = 1; // 计数器初值为1LinkList s, p = L; // p指向第1个结点if (i<1) // i值不合法return ERROR;s = (LinkList)malloc(sizeof(LNode)); // 生成新结点,以下将其插入L中s->data = e; // 给s的data域赋值eif (i == 1) // 插在表头{s->next = L; // 新结点指向原第1个结点L = s; // L指向新结点(改变L)}else{ // 插在表的其余处while (p&&j<i - 1) // 寻找第i-1个结点{j++; // 计数器+1p = p->next; // p指向下一个结点}if (!p) // i大于表长+1return ERROR; // 插入失败s->next = p->next; // 新结点指向原第i个结点p->next = s; // 原第i-1个结点指向新结点}return OK; // 插入成功
}Status ListDelete(LinkList &L, int i, ElemType &e)
{ // 在不设头结点的单链线性表L中,删除第i个元素,并由e返回其值int j = 1; // 计数器初值为1LinkList q, p = L; // p指向第1个结点if (!L) // 表L空return ERROR; // 删除失败else if (i == 1) // 删除第1个结点{L = p->next; // L由第2个结点开始(改变L)e = p->data; // 将待删结点的值赋给efree(p); // 删除并释放第1个结点}else{while (p->next&&j<i - 1) // 寻找第i个结点,并令p指向其前驱{j++; // 计数器+1p = p->next; // p指向下一个结点}if (!p->next || j>i - 1) // 删除位置不合理return ERROR; // 删除失败q = p->next; // q指向待删除结点p->next = q->next; // 待删结点的前驱指向待删结点的后继e = q->data; // 将待删结点的值赋给efree(q); // 释放待删结点}return OK; // 删除成功
}void ListTraverse(LinkList L, void(*vi)(ElemType))
{ // 初始条件:线性表L已存在。操作结果:依次对L的每个数据元素调用函数vi()LinkList p = L; // p指向第1个结点while (p) // p所指结点存在{vi(p->data); // 对p所指结点调用函数vi()p = p->next; // p指向下一个结点}printf("\n");
}
// bo2-4.cpp 不设头结点的单链表(存储结构由c2-2.h定义)的部分基本操作(2个)
#include"C1.h"Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e)
{ // 初始条件:线性表L已存在// 操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,返回OK;//           否则操作失败,pre_e无定义,返回ERRORLinkList q, p = L; // p指向第1个结点while (p->next) // p所指结点有后继{q = p->next; // q指向p的后继if (q->data == cur_e) // p的后继为cur_e{pre_e = p->data; // 将p所指元素的值赋给pre_ereturn OK; // 成功返回OK}p = q; // p的后继不为cur_e,p向后移}return ERROR; // 操作失败,返回ERROR
}Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{ // 初始条件:线性表L已存在// 操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,返回OK,//           否则操作失败,next_e无定义,返回ERRORLinkList p = L; // p指向第1个结点while (p->next) // p所指结点有后继{if (p->data == cur_e) // p所指结点的值为cur_e{next_e = p->next->data; // 将p所指结点的后继结点的值赋给next_ereturn OK; // 成功返回OK}p = p->next; // p指向下一个结点}return ERROR; // 操作失败,返回ERROR
}
// func2-2.cpp 几个常用的函数
#include"C1.H"
Status equal(ElemType c1, ElemType c2)
{ // 判断是否相等的函数if (c1 == c2)return TRUE;elsereturn FALSE;
}int comp(ElemType a, ElemType b)
{ // 根据a<、=或>b,分别返回-1、0或1if (a == b)return 0;elsereturn (a - b) / abs(a - b);
}void print(ElemType c)
{ // 以十进制整型的格式输出元素的值printf("%d ", c);
}void print1(ElemType &c)
{ // 以十进制整型的格式输出元素的值(设c为引用类型)printf("%d ", c);
}void print2(ElemType c)
{ // 以字符型的格式输出元素的值printf("%c ", c);
}
#include "C1.H"int main()
{LinkList La, Lb, Lc;int j, b[7] = { 2,6,8,9,11,15,20 };InitList(La);for (j = 1; j <= 5; j++)ListInsert(La, j, j);ListTraverse(La, print);InitList(Lb);for (j = 1; j <= 5; j++)ListInsert(Lb, j, 2 * j);ListTraverse(Lb, print);Union(La, Lb);ListTraverse(La, print);ClearList(Lb);for (j = 1; j <= 7; j++)ListInsert(Lb, j, b[j - 1]);ListTraverse(Lb, print);MergeList(La, Lb, Lc);ListTraverse(Lc, print);
}

2.3.3 静态链

 // c1.h (文件名)#include<string.h> // 字符串函数头文件#include<ctype.h> // 字符函数头文件#include<malloc.h> // malloc()等#include<limits.h> // INT_MAX等#include<stdio.h> // 标准输入输出头文件,包括EOF(=^Z或F6),NULL等#include<stdlib.h> // atoi(),exit()#include<io.h> // eof()#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等#include<sys/timeb.h> // ftime()#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表// 函数结果状态代码。在教科书第10页#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0// #define INFEASIBLE -1 没使用// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE,第7、8章用到
#include "C1.H"
#define MAX_SIZE 100
#define N 6typedef char ElemType[N];typedef struct {ElemType data;int cur;
}component,SLinkList[MAX_SIZE];int main()
{SLinkList s = { {"",1},{"ZHAO",2},{"QIAN",3},{"SUN",4},{"LI",5} ,{"ZHOU",6}, {"WU",7}, {"ZHENG",8}, {"WANG",0} };int i = s[0].cur;while (i){printf("%s ", s[i].data);i = s[i].cur;}printf("\n");s[4].cur = 9;s[9].cur = 5;strcpy(s[9].data, "SHI");s[6].cur = 8;i = s[0].cur;while (i){printf("%s ", s[i].data);i = s[i].cur;}printf("\n");return 0;
}

2.3.4链表归并

 // c1.h (文件名)
#ifndef C1_H
#define C1_H#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2#include<string.h> // 字符串函数头文件#include<ctype.h> // 字符函数头文件#include<malloc.h> // malloc()等#include<limits.h> // INT_MAX等#include<stdio.h> // 标准输入输出头文件,包括EOF(=^Z或F6),NULL等#include<stdlib.h> // atoi(),exit()#include<io.h> // eof()#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等#include<sys/timeb.h> // ftime()#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表// 函数结果状态代码。在教科书第10页#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0// #define INFEASIBLE -1 没使用// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE,第7、8章用到typedef int ElemType;struct LNode{ElemType data;LNode *next;};typedef LNode *LinkList;void InitList(LinkList &L);void DestoryList(LinkList &L);void ClearList(LinkList &L);Status ListEmpty(LinkList L);int ListLength(LinkList L);Status GetElem(LinkList L, int i, ElemType &e);int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));//寻找前一个节点Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e);//寻找后一个结点Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e);Status ListInsert(LinkList &L, int i, ElemType e);Status ListDelete(LinkList &L, int i, ElemType &e);void ListTraverse(LinkList &L, void(*visit)(ElemType));Status equal(ElemType c1, ElemType c2);int comp(ElemType a, ElemType b);void print(ElemType c);void Union(LinkList &La, LinkList Lb);void MergeList(LinkList La, LinkList Lb, LinkList &Lc);
#endif
#include"C1.H"void InitList(LinkList &L)
{L = (LNode*)malloc(sizeof(LNode));if (!L)exit(OVERFLOW);L->next = NULL;
}void DestoryList(LinkList &L)
{LinkList q;while (L){q = L->next;free(L);L = q;}}
void ClearList(LinkList &L)
{LinkList p = L->next;L->next = NULL;DestoryList(p);
}Status ListEmpty(LinkList L)
{if (L->next)return FALSE;elsereturn TRUE;
}int ListLength(LinkList L)
{int i = 0;LinkList q = L->next;while (q){i++;q = q->next;}return i;
}Status GetElem(LinkList L, int i, ElemType &e)
{int j = 1;LinkList q = L->next;while (q && j < i){j++;q = q->next;}if (!q || j > i)return ERROR;e = q->data;return OK;
}int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{int i = 0;LinkList p = L->next;while (p){i++;if (compare(p->data, e))return i;p = p->next;}return 0;
}
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e)
{LinkList q, p = L->next;while (p->next){q = p->next;if (q->data == cur_e){pre_e = p->data;return OK;}p = q;}return ERROR;
}Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{LinkList p = L->next;while (p->next){if (p->data == cur_e){next_e = p->next->data;return OK;}p = p->next;}return ERROR;
}Status ListInsert(LinkList &L, int i, ElemType e)
{int j = 0;LinkList s, p = L;while (p &&j < i - 1){j++;p = p->next;}if (!p || j > i - 1)return ERROR;s = (LinkList)malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;return OK;
}Status ListDelete(LinkList &L, int i, ElemType &e)
{int j = 0;LinkList q, p = L;while (p->next&&j < i - 1){j++;p = p->next;}if (!p->next || j > i - 1)return ERROR;q = p->next;p->next = q->next;e = q->data;free(q);return OK;
}void ListTraverse(LinkList &L, void(*visit)(ElemType))
{LinkList p = L->next;while (p){visit(p->data);p = p->next;}printf("\n");
}
// func2-2.cpp 几个常用的函数
#include"C1.H"
Status equal(ElemType c1, ElemType c2)
{ // 判断是否相等的函数if (c1 == c2)return TRUE;elsereturn FALSE;
}int comp(ElemType a, ElemType b)
{ // 根据a<、=或>b,分别返回-1、0或1if (a == b)return 0;elsereturn (a - b) / abs(a - b);
}void print(ElemType c)
{ // 以十进制整型的格式输出元素的值printf("%d ", c);
}void print1(ElemType &c)
{ // 以十进制整型的格式输出元素的值(设c为引用类型)printf("%d ", c);
}void print2(ElemType c)
{ // 以字符型的格式输出元素的值printf("%c ", c);
}
#include "C1.H"void Union(LinkList &La, LinkList Lb)
{ElemType e;int La_len, Lb_len;int i;La_len = ListLength(La); // 求线性表La的长度Lb_len = ListLength(Lb); // 求线性表Lb的长度for (i = 1; i <= Lb_len; i++) // 从表Lb的第1个元素到最后1个元素{GetElem(Lb, i, e); // 取表Lb中第i个数据元素的值赋给eif (!LocateElem(La, e, equal)) // 表La中不存在和e相同的元素ListInsert(La, ++La_len, e); // 在表La的最后插入元素e}
}void MergeList(LinkList La, LinkList Lb, LinkList &Lc)
{int i = 1, j = 1, k = 0;int La_len, Lb_len;ElemType ai, bj;InitList(Lc);La_len = ListLength(La);Lb_len = ListLength(Lb);while (i <= La_len&&j <= Lb_len){GetElem(La, i, ai);GetElem(Lb, j, bj);if (ai <= bj){ListInsert(Lc, ++k, ai);++i;}else{ListInsert(Lc, ++k, bj);++j;}}while (i <= La_len){GetElem(La, i++, ai);ListInsert(Lc, ++k, ai);}while (j <= Lb_len){GetElem(La, j++, bj);ListInsert(Lc, ++k, bj);}
}
#include "C1.H"int main()
{LinkList La, Lb, Lc;int j, b[7] = { 2,6,8,9,11,15,20 };InitList(La);for (j = 1; j <= 5; j++)ListInsert(La, j, j);ListTraverse(La, print);InitList(Lb);for (j = 1; j <= 5; j++)ListInsert(Lb, j, 2*j);ListTraverse(Lb, print);Union(La, Lb);ListTraverse(La,print);ClearList(Lb);for (j = 1; j <= 7; j++)ListInsert(Lb, j, b[j - 1]);ListTraverse(Lb, print);MergeList(La, Lb, Lc);ListTraverse(Lc, print);
}

2.3.5循环链表

 // c1.h (文件名)
#ifndef C1_H
#define C1_H#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2#include<string.h> // 字符串函数头文件#include<ctype.h> // 字符函数头文件#include<malloc.h> // malloc()等#include<limits.h> // INT_MAX等#include<stdio.h> // 标准输入输出头文件,包括EOF(=^Z或F6),NULL等#include<stdlib.h> // atoi(),exit()#include<io.h> // eof()#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等#include<sys/timeb.h> // ftime()#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表// 函数结果状态代码。在教科书第10页#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0// #define INFEASIBLE -1 没使用// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE,第7、8章用到typedef int ElemType;struct LNode{ElemType data;LNode *next;};typedef LNode *LinkList;void InitList(LinkList &L);void DestoryList(LinkList &L);void ClearList(LinkList &L);Status ListEmpty(LinkList L);int ListLength(LinkList L);Status GetElem(LinkList L, int i, ElemType &e);int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));//寻找前一个节点Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e);//寻找后一个结点Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e);Status ListInsert(LinkList &L, int i, ElemType e);Status ListDelete(LinkList &L, int i, ElemType &e);void ListTraverse(LinkList &L, void(*visit)(ElemType));Status equal(ElemType c1, ElemType c2);int comp(ElemType a, ElemType b);void print(ElemType c);void print1(ElemType c);void print2(ElemType c);
#endif
#include"C1.H"void InitList(LinkList &L)
{L = (LNode*)malloc(sizeof(LNode));if (!L)exit(OVERFLOW);L->next = L;
}void ClearList(LinkList &L)
{LinkList p,q;L = L->next;p = L->next;while (p != L){q = p->next;free(p);p = q;}L->next = L;
}void DestoryList(LinkList &L)
{ClearList(L);free(L);L = NULL;
}Status ListEmpty(LinkList L)
{if (L->next == L)return TRUE;elsereturn FALSE;
}int ListLength(LinkList L)
{int i = 0;LinkList q = L->next;while (q != L){i++;q = q->next;}return i;
}Status GetElem(LinkList L, int i, ElemType &e)
{int j = 1;LinkList p = L->next->next;if (i <= 0 || i > ListLength(L))return ERROR;while (j<i){j++;p = p->next;}e = p->data;return OK;
}int LocateElem(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{int i = 0;LinkList p = L->next ->next;while (p!=L->next){i++;if (compare(p->data, e))return i;p = p->next;}return 0;
}
Status PriorElem(LinkList L, ElemType cur_e, ElemType &pre_e)
{LinkList q, p = L->next->next;q = p->next;while (q != L->next){if (q->data == cur_e){pre_e = p->data;return OK;}p = q;q = q->next;}return ERROR;
}Status NextElem(LinkList L, ElemType cur_e, ElemType &next_e)
{LinkList p = L->next->next;while (p!=L){if (p->data == cur_e){next_e = p->next->data;return OK;}p = p->next;}return ERROR;
}Status ListInsert(LinkList &L, int i, ElemType e)
{int j = 0;LinkList s, p = L->next;if (i <= 0 || i > ListLength(L) +1)return ERROR;while (j < i - 1){j++;p = p->next;}s = (LinkList)malloc(sizeof(LNode));s->data = e;s->next = p->next;p->next = s;if (p == L)L = s;return OK;
}Status ListDelete(LinkList &L, int i, ElemType &e)
{int j = 0;LinkList q, p = L->next;if (i <= 0 || i > ListLength(L))return ERROR;while (j < i - 1){j++;p = p->next;}q = p->next;p->next = q->next;e = q->data;if (L == q)L = p;free(q);return OK;
}void ListTraverse(LinkList &L, void(*visit)(ElemType))
{LinkList p = L->next->next;while (p!=L->next){visit(p->data);p = p->next;}printf("\n");
}void print(ElemType c)
{printf("%d", c);
}
#include "C1.H"int main()
{LinkList L;ElemType e, e0;Status i;int j, k;InitList(L);for (j = 1; j <= 5; j++)i = ListInsert(L, 1, j);printf("在L的表头一次插入1-5后,L = ");ListTraverse(L, print);i = ListEmpty(L);printf("L是否空?i = %d(1是0否),表L的长度 = %d\n", i, ListLength(L));ClearList(L);printf("清空L之后,L = ");ListTraverse(L, print);i = ListEmpty(L);printf("L是否空?i = %d(1是0否),表L的长度 = %d\n", i, ListLength(L));for (j = 1; j <= 10; j++)i = ListInsert(L, j, j);ListTraverse(L, print);for (j = 1; j <= 2; j++){GetElem(L, j, e0);i = PriorElem(L, e0, e);if (i == ERROR)printf("元素%d无前驱\n", e0);elseprintf("元素%d的前驱为%d\n", e0, e);}for (j = ListLength(L) - 1; j <= ListLength(L); j++){GetElem(L, j, e0);i = NextElem(L, e0, e);if (i == ERROR)printf("元素%d无后继\n", e0);elseprintf("元素%d的后继为%d\n", e0, e);}k = ListLength(L);for (j = k + 1; j >= k; j--){i = ListDelete(L, j, e);if (i == ERROR)printf("%d个元素删除失败\n", j);elseprintf("%d个元素删除成功,值为%d\n", j, e);}printf("依次输出L的元素:");ListTraverse(L, print);//DestoryList(L);//printf("销毁后,L = %u", L);
}

2.3.6静态链表的操做

 // c1.h (文件名)#include<string.h> // 字符串函数头文件#include<ctype.h> // 字符函数头文件#include<malloc.h> // malloc()等#include<limits.h> // INT_MAX等#include<stdio.h> // 标准输入输出头文件,包括EOF(=^Z或F6),NULL等#include<stdlib.h> // atoi(),exit()#include<io.h> // eof()#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等#include<sys/timeb.h> // ftime()#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表// 函数结果状态代码。在教科书第10页#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0// #define INFEASIBLE -1 没使用// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE,第7、8章用到
#include "C1.H"
#define MAX_SIZE 100
#define N 6typedef char ElemType;typedef struct {ElemType data;int cur;
}component, SLinkList[MAX_SIZE];#define DestroyList ClearListint Malloc(SLinkList space)
{int i = space[0].cur;if (i)space[0].cur = space[i].cur;return i;
}void Free(SLinkList space, int k)
{space[k].cur = space[0].cur;space[0].cur = k;
}void InitList(SLinkList L)
{int i;L[MAX_SIZE - 1].cur = 0;for (i = 0; i < MAX_SIZE - 2; i++)L[i].cur = i + 1;L[MAX_SIZE - 2].cur = 0;
}void ClearList(SLinkList L)
{int j, k, i = L[MAX_SIZE - 1].cur;L[MAX_SIZE - 1].cur = 0;k = L[0].cur;L[0].cur = i;while (i){j = i;i = L[i].cur;}L[j].cur = k;
}Status ListEmpty(SLinkList L)
{if (L[MAX_SIZE - 1].cur == 0)return TRUE;elsereturn FALSE;
}int ListLength(SLinkList L)
{int j = 0, i = L[MAX_SIZE - 1].cur;while (i){i = L[i].cur;j++;}return j;
}Status GetElem(SLinkList L, int i, ElemType &e)
{int m, k = MAX_SIZE - 1;if (i<1 || i>ListLength(L))return ERROR;for (m = 1; m <= i; ++m)k = L[k].cur;e = L[k].data;return OK;
}int LocateElem(SLinkList L, ElemType e)
{int i = L[MAX_SIZE - 1].cur;while (i&&L[i].data != e)i = L[i].cur;return i;
}Status PriorElem(SLinkList L, ElemType cur_e, ElemType &pre_e)
{int j, i = L[MAX_SIZE - 1].cur;do {j = i;i = L[i].cur;}while(i&&cur_e != L[i].data);if (i){pre_e = L[j].data;return OK;}return ERROR;
}Status NextElem(SLinkList L, ElemType cur_e, ElemType &next_e)
{int j, i = LocateElem(L, cur_e);if (i){j = L[i].cur;if (j){next_e = L[j].data;return OK;}}return ERROR;
}Status ListInsert(SLinkList L, int i, ElemType e)
{int m, j, k = MAX_SIZE - 1;if (i<1 || i>ListLength(L) + 1)return ERROR;j = Malloc(L);if (j){L[j].data = e;for (m = 1; m < i; m++)k = L[k].cur;L[j].cur = L[k].cur;L[k].cur = j;return OK;}return ERROR;
}Status ListDelete(SLinkList L, int i, ElemType &e)
{int j, k = MAX_SIZE - 1;if (i<1 || i>ListLength(L))return ERROR;for (j = 1; j < i; j++)k = L[k].cur;j = L[k].cur;L[k].cur = L[j].cur;e = L[j].data;Free(L, j);return OK;
}void ListTraverse(SLinkList L, void(*visit)(ElemType))
{int i = L[MAX_SIZE - 1].cur;while (i){visit(L[i].data);i = L[i].cur;}printf("\n");
}

2.7双向链表

 // c1.h (文件名)
#ifndef C1_H
#define C1_H#define LIST_INIT_SIZE 10
#define LIST_INCREMENT 2#include<string.h> // 字符串函数头文件#include<ctype.h> // 字符函数头文件#include<malloc.h> // malloc()等#include<limits.h> // INT_MAX等#include<stdio.h> // 标准输入输出头文件,包括EOF(=^Z或F6),NULL等#include<stdlib.h> // atoi(),exit()#include<io.h> // eof()#include<math.h> // 数学函数头文件,包括floor(),ceil(),abs()等#include<sys/timeb.h> // ftime()#include<stdarg.h> // 提供宏va_start,va_arg和va_end,用于存取变长参数表// 函数结果状态代码。在教科书第10页#define TRUE 1#define FALSE 0#define OK 1#define ERROR 0// #define INFEASIBLE -1 没使用// #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE,第7、8章用到typedef int ElemType;typedef struct DuLNode{ElemType data;DuLNode *next,*prior;}DuLNode,*DuLinkList;void InitList(DuLinkList &L);void DestoryList(DuLinkList &L);void ClearList(DuLinkList &L);Status ListEmpty(DuLinkList L);int ListLength(DuLinkList L);Status GetElem(DuLinkList L, int i, ElemType &e);int LocateElem(DuLinkList L, ElemType e, Status(*compare)(ElemType, ElemType));//寻找前一个节点Status PriorElem(DuLinkList L, ElemType cur_e, ElemType &pre_e);//寻找后一个结点Status NextElem(DuLinkList L, ElemType cur_e, ElemType &next_e);Status ListInsert(DuLinkList &L, int i, ElemType e);Status ListDelete(DuLinkList &L, int i, ElemType &e);void ListTraverse(DuLinkList &L, void(*visit)(ElemType));void ListTraverseBack(DuLinkList &L, void(*visit)(ElemType));DuLinkList GetElemP(DuLinkList L, int i);Status equal(ElemType c1, ElemType c2);int comp(ElemType a, ElemType b);void print(ElemType c);void print1(ElemType c);void print2(ElemType c);
#endif
#include"C1.H"void InitList(DuLinkList &L)
{L = (DuLNode*)malloc(sizeof(DuLNode));if (!L)exit(OVERFLOW);else{L->next = L->prior = L;}
}void ClearList(DuLinkList &L)
{DuLinkList p = L->next;while (p != L){p = p->next;free(p->prior);}L->next = L->prior = L;
}void DestoryList(DuLinkList &L)
{ClearList(L);free(L);L = NULL;
}Status ListEmpty(DuLinkList L)
{if (L->next == L &&L->prior == L)return TRUE;elsereturn FALSE;
}int ListLength(DuLinkList L)
{int i = 0;DuLinkList q = L->next;while (q != L){i++;q = q->next;}return i;
}Status GetElem(DuLinkList L, int i, ElemType &e)
{int j = 1;DuLinkList p = L->next;while (p != L && j<i){j++;p = p->next;}if (p == L || j > i)return ERROR;e = p->data;return OK;
}int LocateElem(DuLinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{int i = 0;DuLinkList p = L->next;while (p != L){i++;if (compare(p->data, e))return i;p = p->next;}return 0;
}
Status PriorElem(DuLinkList L, ElemType cur_e, ElemType &pre_e)
{DuLinkList p = L->next->next;while (p != L){if (p->data == cur_e){pre_e = p->prior->data;return OK;}p = p->next;}return ERROR;
}Status NextElem(DuLinkList L, ElemType cur_e, ElemType &next_e)
{DuLinkList p = L->next->next;while (p != L){if (p->prior->data == cur_e){next_e = p->data;return OK;}p = p->next;}return ERROR;
}DuLinkList GetElemP(DuLinkList L, int i)
{int j;DuLinkList p = L;if (i < 0 || i>ListLength(L))return ERROR;for (j = 1; j <= i; j++)p = p->next;return p;
}Status ListInsert(DuLinkList &L, int i, ElemType e)
{int j = 0;DuLinkList s, p = L->next;if (i <= 0 || i > ListLength(L) + 1)return ERROR; p = GetElemP(L, i - 1);s = (DuLinkList)malloc(sizeof(DuLNode));s->data = e;s->next = p->next;s->prior = p;p->next->prior = s;p->next = s;return OK;
}Status ListDelete(DuLinkList &L, int i, ElemType &e)
{int j = 0;DuLinkList p;if (i <= 1)return ERROR;p = GetElemP(L, i);if (!p)return ERROR;e = p->data;p->prior->next = p->next;p->next->prior = p->prior;free(p);return OK;
}void ListTraverse(DuLinkList &L, void(*visit)(ElemType))
{DuLinkList p = L->next;while (p != L){visit(p->data);p = p->next;}printf("\n");
}void ListTraverseBack(DuLinkList &L, void(*visit)(ElemType))
{DuLinkList p = L->prior;while (p != L){visit(p->data);p = p->prior;}printf("\n");
}void print(ElemType c)
{printf("%d", c);
}Status equal(ElemType c1, ElemType c2)
{if (c1 == c2)return TRUE;elsereturn FALSE;
}
// main2-6.cpp 检验bo2-7.cpp的主程序
#include"c1.h"void main()
{DuLinkList L;int i, n = 4;Status j;ElemType e;InitList(L); // 初始化线性表Lfor (i = 1; i <= 5; i++) // 依次插入1~5ListInsert(L, i, i); // 在第i个结点之前插入iprintf("逆序输出链表:");ListTraverseBack(L, print); // 逆序输出j = GetElem(L, 2, e); // 将链表的第2个元素赋值给eif (j)printf("链表的第2个元素值为%d\n", e);elseprintf("不存在第2个元素\n");i = LocateElem(L, n, equal);if (i)printf("等于%d的元素是第%d个\n", n, i);elseprintf("没有等于%d的元素\n", n);j = PriorElem(L, n, e);if (j)printf("%d的前驱是%d,", n, e);elseprintf("不存在%d的前驱\n", n);j = NextElem(L, n, e);if (j)printf("%d的后继是%d\n", n, e);elseprintf("不存在%d的后继\n", n);ListDelete(L, 2, e); // 删除并释放第2个结点printf("删除第2个结点,值为%d,其余结点为 ", e);ListTraverse(L, print); // 正序输出printf("链表的元素个数为%d,", ListLength(L));printf("链表是否空?%d(1:是 0:否)\n", ListEmpty(L));ClearList(L); // 清空链表printf("清空后,链表是否空?%d(1:是 0:否)\n", ListEmpty(L));DestoryList(L);
}

高一凡-数据结构第2章-线性表相关推荐

  1. 高一凡-数据结构第1章-绪论

    高一凡-数据结构第1章-绪论 1.1三元组抽象数据类型Triplet 1.初始化InitTriplet 2.销毁三元组DestoryTriple 3.获取元素值Get 4.指定赋值Put 5.检查升序 ...

  2. 高一凡-数据结构第3章-栈与队列

    高一凡-数据结构第3章-栈与队列 3.1栈 3.1.1栈的数据结构 3.1.2接口 3.1.3实现 VS2015实例代码包: 3.1栈 3.1.1栈的数据结构 struct SqStack {SEle ...

  3. 【算法基础】数据结构导论第二章-线性表.pptx

    上课的课件分享,适合教学用. 文末提供下载 已发布:数据结构导论第一章-绪论 本文参考百度文库的多篇文章. 如需下载ppt文件,请回复"sjjg2" ppt有动画效果.

  4. 期末复习之数据结构 第2章 线性表

    目录 一.课本知识点 1.线性结构 2.线性表 3.线性表的顺序表示 4.顺序表的基本操作 5.线性表的链式表示 6.链表的基本操作 总结 二.练习题 一.课本知识点 1.线性结构 定义:若结构是非空 ...

  5. [XJTUSE]数据结构学习——第一章 线性表 1.3 单链表的实现(JAVA)

    文章目录 1.3 单链表的实现(JAVA) 1.curr指针与头结点的说明 2.插入和删除操作的说明 插入 删除 1.3 单链表的实现(JAVA) 链表是由一系列叫做表的结点(node)的对象组成的, ...

  6. 大话数据结构读书笔记艾提拉总结 查找算法 和排序算法比较好 第1章数据结构绪论 1 第2章算法 17 第3章线性表 41 第4章栈与队列 87 第5章串 123 第6章树 149 第7章图 21

    大话数据结构读书笔记艾提拉总结 查找算法 和排序算法比较好 第1章数据结构绪论 1 第2章算法 17 第3章线性表 41 第4章栈与队列 87 第5章串 123 第6章树 149 第7章图 211 第 ...

  7. 数据结构 严蔚敏 第二章 线性表

    数据结构 严蔚敏 第二章 线性表 线性表:由n个(n>=0)数据特征相同的元素构成的有限序列. 线性表的类型定义表示和实现 顺序表 存储单元地址连续 随机存取 若每个元素占用 m 个存储单元,以 ...

  8. 数据结构第二章-线性表(详细知识点总结)

    目录 第二章 线性表 2.1 线性表的定义和操作 2.1.1 线性表的定义 2.1.2 线性表的基本操作 2.2线性表的顺序表示 2.2.1 顺序表的定义 2.2.2 顺序表上基本操作的实现 2.3 ...

  9. 2022天勤考研数据结构笔记 第2章 线性表

    2022天勤考研数据结构笔记 第2章 线性表(更新中) 第2章 线性表 2.1 结构体定义 2.2 顺序表 2.3 单链表 2.4 双链表 2.5 循环链表 2.6 逆置问题(408重要考点) 第2章 ...

最新文章

  1. 线段树 ---- 2021牛客多校第一场 J Journey among Railway Stations [线段树维护区间可行性判断]
  2. OpenCV camshift目标追踪
  3. 根据后续数组重建搜索二叉树
  4. 谈谈“学习”这件事儿
  5. 40.4. SOCKS
  6. 三维点云学习(5)2-Deep learning for Point Cloud-PointNet
  7. URLEncoder与URLDecoder
  8. Android摄影App,摄影爱好者必备的Android摄影App推介
  9. python 极客学院 正则表达式
  10. 利用Winhex,OllyDbg和W32Dasm破解USB监控器
  11. ios 纯代码怎么适配ipad_iOS屏幕适配(纯代码)
  12. 【MM32F5270开发板试用】定制MicroPython及读取MPU6050数据到OLED1306
  13. 求解两点间最短路径的算法
  14. 【渝粤教育】21秋期末考试国际私法10216k1
  15. 浅谈PageRank
  16. Python3从搜狐国际新闻抓取---尝试版
  17. AXI接口协议详解-AXI总线、接口、协议
  18. JavaScript - 模拟键盘输入支付密码
  19. java—set创建迭代器的两个方法
  20. Three.js 地理坐标和三维空间坐标的转换

热门文章

  1. mail命令发送html格式的电子邮件
  2. 中科大徐童:AI×Talent数据驱动的智能人才计算
  3. 计算机中的虚拟ip,如何设置电脑虚拟IP
  4. 自己架设云游戏服务器需要注意什么?
  5. 计算机科学与技术(现代教育技术),现代教育技术
  6. EndNote的下载、安装与配置!(绝对保姆级教程)!
  7. 微型计算机控制系统设计方法,第3章 机电一体化中微型计算机控制系统及接口设计...
  8. java递归实现多级树
  9. *p++与*(p++)与(*p)++的区别
  10. 仿链家地图找房的简单实现 1