一、线性表的存储表示
1、顺序表
线性表的顺序表示又称为顺序表。
顺序表的静态分配存储表示
//线性表的静态分配顺序存储结构
typedef int ElemType;
typedef struct { //顺序表的定义
ElemType elem[LISTSIZE];
int length; //当前长度
}Sqlist;
顺序表的动态分配存储表示
//线性表的动态分配顺序存储结构
#define LIST_INIT_SIZE 100 //初始分配量
#define LISTINCREMENT 10 //分配增量
typedef int ElemType;
typedef struct {
ElemType* elem; // 存储空间基址
int length; // 当前长度
int listsize; // 当前分配的存储容量(以sizeof(ElemType)为单位)
} SqList; // 俗称 顺序表
//线性表的初始化操作:elem=new ElemType[LIST_INIT_SIZE]
//或者elem=(ElemType*)malloc(sizeof(ElemType)*LIST_INIT_SIZE)
其中,线性表的初始化操作为:elem=new ElemType[LIST_INIT_SIZE]
或者elem=(ElemType*)malloc(sizeof(ElemType)*LIST_INIT_SIZE)
2、线性链表
线性表的链接存储表示
最简单的链表为线性表,一般描述为
typedef int DataType;
typedef struct LNode {
int data;
struct LNode* next;
}LNode, * LinkList;
动态分配结点空间的语句
s= (LinkNode*)malloc(sizeof(LinkNode)); //s为指示链表结点存储地址的指针
其他形式的链表,如 循环链表
双向循环链表
二、线性表的基本操作
1、线性表的静态存储顺序表的基本操作
//初始化操作(创建一个空表)
void InitList(Sqlist& L) {
L.length = 0;
}
//销毁操作
void DestroyList(Sqlist& L) {
free(L.elem);
L.length = 0;
}
//求表长
int GetLength(Sqlist& L) {
return L.length;
}
//查找第i个元素(元素从1开始算)
ElemType GetElem(Sqlist& L, int i) {
if (i < L.length) {
return L.elem[i - 1];
}
return 0;
}
//查找已知元素位置(元素从1开始算)
int LocateElem(Sqlist& L, ElemType e) {
for (int i = 0; i < L.length; i++) {
if (L.elem[i] == e) {
return i + 1;
}
}
return 0;
}
//插入操作(将新元素e插入第i个元素前面)(元素从1开始算)
int InsertList(Sqlist& L, int i, ElemType e) {
if (i <= L.length + 1) {
for (int j = L.length; j > i - 1; j--) {
L.elem[j] = L.elem[j - 1];
}
L.elem[i - 1] = e;
L.length++;
return 1;
}
return 0;
}
//删除操作(删除第i个元素)(元素从1开始算)
int DeleteList(Sqlist& L, int i) {
if (i <= L.length) {
for (int j = i - 1; j < L.length-1; j++) {
L.elem[j] = L.elem[j + 1];
}
L.length--;
return 1;
}
return 0;
}
//读取第i个元素(元素从1开始算)
ElemType PrintElem(Sqlist& L, int i) {
if (i < L.length) {
printf("%d\n", L.elem[i - 1]);
return 1;
}
return 0;
}
2、线性表的动态存储顺序表的基本操作
//线性表的动态存储顺序表的基本操作
//初始化操作(创建一个空表)
void InitList(SqList& L) {
L.elem = (ElemType*)malloc(sizeof(ElemType) * LIST_INIT_SIZE);
L.length = 0;
L.listsize = LIST_INIT_SIZE;
}
//销毁操作
void DestroyList(SqList& L) {
free(L.elem);
L.length = NULL;
L.listsize = NULL;
}
//求表长
int GetLength(SqList& L) {
return L.length;
}
//查找第i个元素(元素从1开始算)
ElemType GetElem(SqList& L, int i) {
if (i < L.length) {
return L.elem[i - 1];
}
return 0;
}
//查找已知元素位置(元素从1开始算)
int LocateElem(SqList& L, ElemType e) {
for (int i = 0; i < L.length; i++) {
if (L.elem[i] == e) {
return i + 1;
}
}
return 0;
}
//动态表扩充存储空间
void AddSqList(SqList& L) {
int newSize;
ElemType* newArray;
newSize = LISTINCREMENT + LIST_INIT_SIZE;
newArray = (ElemType*)malloc(sizeof(ElemType) * newSize);
for (int i = 0; i < L.length; i++) {
newArray[i] = L.elem[i];
}
L.elem = newArray;
L.listsize = newSize;
}
//插入操作(将新元素e插入第i个元素前面)(元素从1开始算)
int InsertList(SqList& L, int i, ElemType e) {
if (L.length == L.listsize) {
AddSqList(L);
}
if (i <= L.length + 1) {
for (int j = L.length; j > i - 1; j--) {
L.elem[j] = L.elem[j - 1];
}
L.elem[i - 1] = e;
L.length++;
return 1;
}
return 0;
}
//删除操作(删除第i个元素)(元素从1开始算)
int DeleteList(SqList& L, int i) {
if (i <= L.length) {
for (int j = i - 1; j < L.length - 1; j++) {
L.elem[j] = L.elem[j + 1];
}
L.length--;
return 1;
}
return 0;
}
//读取第i个元素(元素从1开始算)
ElemType PrintElem(SqList& L, int i) {
if (i < L.length) {
printf("%d\n", L.elem[i - 1]);
return 1;
}
return 0;
}
3、单链表的基本操作
//单链表的基本操作
//初始化
void InitList(LinkList& L) {
L= (LinkList)malloc(sizeof(LNode));//头指针
L->next = NULL;
}
// 取第i个数据元素
int GetElem(LinkList& L, int i, int e) {
//L是带头结点的链表的头指针,以e返回第i个元素
LinkList p = L->next;
int j = 1;//p指向第一个结点,j为计数器
while (p && j < i) {
p = p->next;
j++;
}
if (!p) {
return 0;
}
e = p->data;
return e;
}
// 插入数据元素
int ListInsert(LinkList&L,int i,int e) {
//将元素e插入第i个结点之前
LinkList p = L;
int j = 0;
while (p && j < i - 1) {
p = p->next;
j++;
}
if (!p || j > i - 1) {
return 0;
}
LinkList s = new LNode;
if (s == NULL)return 0;
s->data = e;
s->next = p->next;
p->next = s;
return 1;
}
// 删除数据元素
int ListDelete(LinkList& L, int i) {
//删除第i个结点
LinkList p = L;
int j = 0;
while (p->next && j < i - 1) {
p = p->next;
j++;
}
if (!(p->next) || j > i - 1) {
return 0;
}
LinkList q = p->next;
p->next = q->next;
return 1;
}
// 重置线性表为空表
int ClearList(LinkList& L) {
free(L);
InitList(L);
return 1;
}
// 生成含 n 个数据元素的链表(尾插法)
void CreateList(LinkList& L, int n) {
L= (LinkList)malloc(sizeof(LNode));
LinkList rear = L;//设置尾指针
for (int i = 0; i < n; i++) {
rear->next= (LinkList)malloc(sizeof(LNode));
rear = rear->next;
scanf_s("%d", &(rear->data));
}
}
//生成含 n 个数据元素的链表(头插法)
void CreateList_L(LinkList& L, int n) {
LinkList p;
L = (LinkList)malloc(sizeof(LNode));
L->next = NULL;
for (int i = n; i > 0; --i) {
p = (LinkList)malloc(sizeof(LNode));
scanf_s("%d", &(p->data));
p->next = L->next;
L->next = p;
}
}//CreateList_L
//输出单链表L
void listPrint(LinkList& L)
{
printf("单链表:");
LNode* p = L;
while (p->next != NULL)
{
printf("%d ", p->next->data);
p = p->next;
}
printf("\n");
}
三、例题
设计一个算法,顺序读出数组a[n]中的元素数值,建立一个带头结点的单链表,次序与a[n]相同
尾插法
void createListR(LinkList& list, DataType a[], int n) {
//根据数组a[n]建立一个单链表,单链表各元素次序与a[n]各元素相同
list = (LinkNode*)malloc(sizeof(LinkNode)); //创建头节点
LinkNode* rear = list; //设置尾指针
for (int i = 0; i < n; i++) { //尾插法
rear->link = (LinkNode*)malloc(sizeof(LinkNode)); //为rear下一个位置分配空间
rear= rear->link;
rear->data = a[i];
}
}
设计一个算法,顺序读出数组a[n]中的元素数值,建立一个带头结点的单链表,次序与a[n]相反
头插法
void createListF(LinkList& list, DataType a[], int n) {
//根据数组a[n]建立一个单链表,单链表各元素次序与a[n]各元素相反
LinkList s;
list=(LinkNode*)malloc(sizeof(LinkNode)); //创建头结点
list->link = NULL; //尾结点设置为NULL
for (int i = 0; i < n; i++) { //头插法
s= (LinkNode*)malloc(sizeof(LinkNode));
s->data = a[i];
s->link = list->link;
list->link = s;
}
}
单链表的输出
void listPrint(LinkNode* L)
{
printf("单链表:");
LinkNode* p = L; //将头指针赋给p
while (p->link != NULL)
{
printf("%d ", p->link->data); //输出单链表p->link的结点数据
p = p->link; //将p向后移一个位置
}
printf("\n");
}
找出单链表中最大值
void Max(LinkList L) {
LinkList p;
int max=0;
for (p = L->link; p != NULL; p = p->link) { //用p遍历链表
if (max < p ->data) {
max = p->data;
}
}
printf_s("%d", max);
}
计算单链表长度
void Length(LinkList& L) {
LinkList p=L->link;
int length = 0;
while (p != NULL) {
p = p->link; length++;
}
printf_s("%d", length);
}
找出单链表倒数第k个元素
int SearchK(LinkList list, int k) {
LinkList p, q; int count = 0; //计数器赋初值
for (p = q = list->link; p != NULL; p = p->link) { //用遍历链表
if (count < k)
count++; //计数器加一
else
q = q->link; //在count>=k时开始移动
}
if (count < k)
return 0; //链表长度小于k查找失败
else {
printf("%d\n", q->data);
return 1; //查找成功
}
}