数据结构基础内容(第二篇:线性结构)

线性结构

一元多项式

f(x) = a0 + a1x+...+anx

方法一:顺序存储结构直接表示

a[i]: 系数

方法二:顺序存储表示非零项

用结构数组表示:系数与指数的二元组

方法三:链表结构存储非零项

coef expon link;

```c

typedef struct PolyNode *polynomial;

truct PolyNode{

int coef;

int expon;

polynomial link;

}

```

线性表 Linear List

同类型数据元素构成有序序列的线性结构。

数据对象集:n个元素构成的有序序列

操作集:线性表L属于List, 整数表示位置,元素x属于ElementType。操作:

* List MakeEmpty(): 初始化一个空表

* ElementType FindKth(int K, List L); 根据位序K,返回相应元素

* int Find(ElementType x, List L); 在表中查找X第一次出现的位置

* void insert(ElementType X, int i, List L); 插入

* void Delete(int i, List l); 删除

* int length(List L); 返回长度

线性存储序列的实现

```c

typedef struct LNode *List;

struct LNode{

ElementType Data[MAXSIZE];

int Last;

};

struct LNode L;

List PtrL;

```

访问元素:L.Data[i] or PtrL->Data[i]

线性表的长度:L.Last+1 或 PtrL->Last+1 (last代表位置,因为从零开始所以是n-1)

* 初始化

```c

List MakeEmpty( )

{

List PtrL;

PtrL = (List )malloc( sizeof(struct LNode) );

PtrL->Last = -1; //last若为0 则表示表里有一个元素在0号位置

return PtrL;

}

```

* 查找

```c

int Find( ElementType X, List PtrL ) {

int i = 0;

while( i <= PtrL->Last && PtrL->Data[i]!= X )

i++;

if (i > PtrL->Last) return -1;

/* 如果没找到,返回-1(因破坏第一个条件而跳出循环) */

else return i; /* 找到后返回的是存储位置 */ }

}

```

平均查找次数(n +1)/2,平均时间性能为 O(n)

* 插入

第 i (1≤i≤n+1)个位置上插入一个值为X的新元素(其实是插在数组的第i-1个位置,因为数组从0开始标)先移动再插入,n挪到n+1,n-1挪到n, ...,i-1挪到i

在链表L中的第一个位置插入元素X,如下,MAXSIZE代表链表的size

```c

void Insert( ElementType X, int i, List PtrL ) {

int j;

/* 表空间已满,不能插入*/

if ( PtrL->Last == MAXSIZE-1 )

{

printf("表满");

return;

}

/*检查插入位置的合法性*/

if ( i < 1 || i > PtrL->Last+2)

{

printf("位置不合法");

return;

}

/* 开始挪位子,从最后的一位last开始直到i-1 */

for ( j = PtrL->Last; j >= i-1; j-- )

PtrL->Data[j+1] = PtrL->Data[j];

PtrL->Data[i-1] = X; /*新元素插入*/

PtrL->Last++; /*Last仍指向最后元素*/

return;

}

```

平均移动次数为 n /2,

/*检查插入位置的合法性*/ 平均时间性能为 O(n)

* 删除

删除第i个位置上的元素,i在1到n之间,对应数组下表0到n-1

删掉下表为i-1的元素,下标i的元素挪到i-1...

```c

void Delete( int i, List PtrL )

{

intj;

/*检查空表及删除位置的合法性*/

if( i < 1 || i > PtrL->Last+1 )

{

printf ("不存在第%d个元素", i );

return ;

}

/*将 ai+1~ an顺序向前移动, 从第i位开始,到last */

for ( j = i; j <= PtrL->Last; j++ )

PtrL->Data[j-1] = PtrL->Data[j];

PtrL->Last--; /*Last仍指向最后元素*/

return;

}

```

平均移动次数为 (n-1) /2

平均时间性能为 O(n)

链式存储的实现

一个线性表用数组存储的时候,相邻的元素不仅逻辑上不仅逻辑上相邻,物理上也是相邻的。而链表通过链连接,建立数据元素的逻辑关系。

```c

typedef struct LNode *List;

struct LNode

{

ElementType Data;

List Next;

};

struct Lnode L;

List PtrL;

```

* 求表长

用临时指针p指向链表头Ptrl,然后遍历,直到null

```c

int Length ( List PtrL )

{

List p = PtrL; /* p指向表的第一个结点*/

int j=0;

while ( p )

{

p = p->Next;

j++; /* 当前p指向的是第 j 个结点*/

}

return j;

}

```

* 查找

  1. 按序号查找 根据位序K,返回相应元素 FindKth(int K, List L)

```c

List FindKth( int K, List PtrL )

{

List p = PtrL;

int i=1; // i代表第几给元素。因为一开始p指向第一个元素,所以i=1

while (p !=NULL && i < K )

{

p = p->Next;

i++;

}

if ( i == K ) /* 找到第K个,返回指针 */

return p;

else return NULL; /* 没找到第K个,循环因为 p=NULL 而退出 */

}

```

  1. 按值查找:Find(ElementType x, List L)

```c

List Find( ElementType X, List PtrL )

{

List p = PtrL;

while ( p!=NULL && p->Data != X ) // 条件1表不空,条件2没找到X,就继续

p = p->Next;

return p; //找到了:返回节点p。没找到返回p = NULL

}

```

* 插入

在第 i-1 (1≤i≤n+1) 个结点后插入一个值为X的新结点

  1. 先构造一个新结点,用s指向; mallo

  2. 再找到链表的第 i-1个结点,用p指向;

  3. 然后修改指针,插入结点 ( p之后插入新结点是 s)

```c

s-> next = p -> next;

p -> next = s

```

实现

```c

List Insert( ElementType X, int i, List PtrL )

{

List p, s;

if ( i == 1 ) /* 新结点插入在表头 */

{

s = (List)malloc(sizeof(struct LNode)); /*申请、填装结点s */

s->Data = X;

s->Next = PtrL;

return s; // s成为新的head,返回出去

}

p = FindKth( i-1, PtrL ); /* 查找第i-1个结点 */

if ( p == NULL )

{

printf("参数i错");

return NULL;

}

else

{

s = (List)malloc(sizeof(struct LNode)); /*申请、填装结点*/

s->Data = X;

s->Next = p->Next; /*新结点插入在第i-1个结点的后面*/

p->Next = s;

return PtrL;

}

}

```

* 删除

删除链表的第 i (1≤i≤n) 个位置上的节点

  1. 先找到链表的第 i-1个结点,用p指向;

  2. 再用指针s指向要被删除的结点(p的下一个结点);

  3. 然后修改指针,删除s所指结点; `p->next = s->next`

  4. 最后释放s所指结点的空间。

实现

```c

List Delete( int i, List PtrL )

{

List p, s;

if ( i == 1 )

{ /* 若要删除的是表的第一个结点 */

s = PtrL; /*s指向第1个结点*/

if (PtrL!=NULL)

PtrL = PtrL->Next; /*从链表中删除*/

else

return NULL; // 如果本身就是空链表,return NULL

free(s);

return PtrL;

}

p = FindKth( i-1, PtrL ); /*查找第i-1个结点*/

if ( p == NULL )

{

printf("第%d个结点不存在", i-1);

}

else if ( p->Next == NULL )

{

printf("第%d个结点不存在", i);

}else

{

s = p->Next; /*s指向第i个结点*/

p->Next = s->Next; /*从链表中删除*/

free(s); /*释放被删除结点 */

return PtrL;

}

}

```

广义表 Generalized List

二元多项式

可以将上述二元多项式看成关于x 的一元多项式

矩阵可以用二维数组表示,但二维数组表示有两个缺陷:

  1. 一是数组的大小需要事先确定

  2. 对于"稀疏矩阵 ",将造成大量的存储空间浪费。

采用一种典型的多重链表------十字链表来存储稀疏矩阵

* 只存储矩阵非0元素项 结点的数据域:行坐标Row、列坐标Col、数值Value

* 每个结点通过两个指针域,把同行、同列串起来

* 行指针(或称为向右指针)Right

* 列指针(或称为向下指针)Down

Term 代表非0项

特殊Term A 代表4行5列,7个非零项

相关推荐
晨非辰40 分钟前
#C语言——学习攻略:深挖指针路线(三)--数组与指针的结合、冒泡排序
c语言·开发语言·数据结构·学习·算法·排序算法·visual studio
小码哥学习中40 分钟前
centos7 安装mysql5.7.36和mysql8.0.32(同时存在)
数据结构
神经兮兮的小饼7 小时前
字符串是数据结构还是数据类型?
数据结构·字符串
遇见尚硅谷9 小时前
C语言:20250728学习(指针)
c语言·开发语言·数据结构·c++·笔记·学习·算法
java叶新东老师10 小时前
解决windows系统下 idea、CLion 控制台中文乱码问题
java·windows·intellij-idea
拳里剑气12 小时前
C语言:顺序表(上)
c语言·开发语言·数据结构·学习方法
积极向上的zzz13 小时前
java中一些数据结构的转换
java·开发语言·数据结构
每天都在想吃啥13 小时前
day22 哈希表和二叉树
数据结构·哈希算法·散列表
Das114 小时前
【初识数据结构】CS61B 中的归并排序和选择排序
数据结构·算法·排序算法