高一凡-数据结构第2章-线性表
高一凡-数据结构第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三元组抽象数据类型Triplet 1.初始化InitTriplet 2.销毁三元组DestoryTriple 3.获取元素值Get 4.指定赋值Put 5.检查升序 ...
- 高一凡-数据结构第3章-栈与队列
高一凡-数据结构第3章-栈与队列 3.1栈 3.1.1栈的数据结构 3.1.2接口 3.1.3实现 VS2015实例代码包: 3.1栈 3.1.1栈的数据结构 struct SqStack {SEle ...
- 【算法基础】数据结构导论第二章-线性表.pptx
上课的课件分享,适合教学用. 文末提供下载 已发布:数据结构导论第一章-绪论 本文参考百度文库的多篇文章. 如需下载ppt文件,请回复"sjjg2" ppt有动画效果.
- 期末复习之数据结构 第2章 线性表
目录 一.课本知识点 1.线性结构 2.线性表 3.线性表的顺序表示 4.顺序表的基本操作 5.线性表的链式表示 6.链表的基本操作 总结 二.练习题 一.课本知识点 1.线性结构 定义:若结构是非空 ...
- [XJTUSE]数据结构学习——第一章 线性表 1.3 单链表的实现(JAVA)
文章目录 1.3 单链表的实现(JAVA) 1.curr指针与头结点的说明 2.插入和删除操作的说明 插入 删除 1.3 单链表的实现(JAVA) 链表是由一系列叫做表的结点(node)的对象组成的, ...
- 大话数据结构读书笔记艾提拉总结 查找算法 和排序算法比较好 第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 第 ...
- 数据结构 严蔚敏 第二章 线性表
数据结构 严蔚敏 第二章 线性表 线性表:由n个(n>=0)数据特征相同的元素构成的有限序列. 线性表的类型定义表示和实现 顺序表 存储单元地址连续 随机存取 若每个元素占用 m 个存储单元,以 ...
- 数据结构第二章-线性表(详细知识点总结)
目录 第二章 线性表 2.1 线性表的定义和操作 2.1.1 线性表的定义 2.1.2 线性表的基本操作 2.2线性表的顺序表示 2.2.1 顺序表的定义 2.2.2 顺序表上基本操作的实现 2.3 ...
- 2022天勤考研数据结构笔记 第2章 线性表
2022天勤考研数据结构笔记 第2章 线性表(更新中) 第2章 线性表 2.1 结构体定义 2.2 顺序表 2.3 单链表 2.4 双链表 2.5 循环链表 2.6 逆置问题(408重要考点) 第2章 ...
最新文章
- 线段树 ---- 2021牛客多校第一场 J Journey among Railway Stations [线段树维护区间可行性判断]
- OpenCV camshift目标追踪
- 根据后续数组重建搜索二叉树
- 谈谈“学习”这件事儿
- 40.4. SOCKS
- 三维点云学习(5)2-Deep learning for Point Cloud-PointNet
- URLEncoder与URLDecoder
- Android摄影App,摄影爱好者必备的Android摄影App推介
- python 极客学院 正则表达式
- 利用Winhex,OllyDbg和W32Dasm破解USB监控器
- ios 纯代码怎么适配ipad_iOS屏幕适配(纯代码)
- 【MM32F5270开发板试用】定制MicroPython及读取MPU6050数据到OLED1306
- 求解两点间最短路径的算法
- 【渝粤教育】21秋期末考试国际私法10216k1
- 浅谈PageRank
- Python3从搜狐国际新闻抓取---尝试版
- AXI接口协议详解-AXI总线、接口、协议
- JavaScript - 模拟键盘输入支付密码
- java—set创建迭代器的两个方法
- Three.js 地理坐标和三维空间坐标的转换
热门文章
- mail命令发送html格式的电子邮件
- 中科大徐童:AI×Talent数据驱动的智能人才计算
- 计算机中的虚拟ip,如何设置电脑虚拟IP
- 自己架设云游戏服务器需要注意什么?
- 计算机科学与技术(现代教育技术),现代教育技术
- EndNote的下载、安装与配置!(绝对保姆级教程)!
- 微型计算机控制系统设计方法,第3章 机电一体化中微型计算机控制系统及接口设计...
- java递归实现多级树
- *p++与*(p++)与(*p)++的区别
- 仿链家地图找房的简单实现 1