数据结构 线性表的顺序存储和链式存储,以及基本操作、单链表例题

一、线性表的存储表示

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张图片 

双向循环链表

 数据结构 线性表的顺序存储和链式存储,以及基本操作、单链表例题_第2张图片

数据结构 线性表的顺序存储和链式存储,以及基本操作、单链表例题_第3张图片

二、线性表的基本操作

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个元素

数据结构 线性表的顺序存储和链式存储,以及基本操作、单链表例题_第4张图片

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;   //查找成功
		}
}

你可能感兴趣的:(笔记,数据结构,数据结构,链表,list)