线性表的应用
线性表的合并
例子: 求解一般集合的并集问题。
已知两个集合
合并后
算法如下:
/**
* 线性表的合并
* @param a 线性表 a
* @param b 线性表 b
*/
export function union<T>(a: List<T>, b: List<T>) {
let aLength = a.length
for (let i = 1; i <= b.length; i++) {
const ele = getElement(b, i)
if (!find(a, ele)) {
insert(a, ++aLength, ele)
}
}
}假设
有序表的合并
若线性表中的元素之间可以比较,并且元素在线性表中依值递增或递减有序排列,则称该线性表为有序表(Ordered List)。
例子:求解有序集合的并集问题。
有序集合是指集合中的元素有序排列。已知有两个有序集合
则
算法如下:
/**
* 有序表的合并
* @param a 有序表 a
* @param b 有序表 b
*/
export function unionOrdered<T>(a: List<T>, b: List<T>) {
let preva = a.headNode.next
let prevb = b.headNode.next
const _union = new List<T>()
let prevc = _union.headNode
while (preva && prevb) {
if (!preva.data || !prevb.data)
throw new Error('Elements must be sortable!')
if (preva.data <= prevb.data) {
if (preva.data === prevb.data) {
prevb = prevb.next
}
prevc.next = new ListNode(preva.data)
prevc = prevc.next
preva = preva.next
} else {
prevc.next = new ListNode(prevb.data)
prevc = prevc.next
prevb = prevb.next
}
_union.length++
}
prevc.next = preva ?? prevb
while (prevc.next) {
_union.length++
prevc = prevc.next
}
return _union
}假设
一元多项式的运算
一元多项式按升幂写成:
要求:实现两个一元多项式的相加运算。
可以看出,一元多项式由
每一项的指数
假设
设
对于此类线性表,我们可以使用数组来实现。
数组
例如:
| 指数(下标 | 0 | 1 | 2 | 3 | 4 |
|---|---|---|---|---|---|
| 系数 | 10 | 5 | -4 | 3 | 2 |
算法如下:
/**
* 两个一元多项式相加
* @param p 一元多项式
* @param q 一元多项式
*/
export function add(p: number[], q: number[]) {
const length = Math.max(p.length, q.length)
const result: number[] = []
for (let i = 0; i < length; i++) {
result[i] = (p[i] ?? 0) + (q[i] ?? 0)
}
return result
}稀疏多项式
在通常的应用中,我们更可能遇到的多项式是稀疏多项式[1]。
例如:
在处理上面这种多项式时,就要用一个长度为 20001 的线性表表示,但表中只有 3 个非零元素。此时将极大地浪费存储空间。由于线性表的元素可以包含多个数据项,由此可改变元素设定,对多项式的每一项,使用(系数,指数)唯一确定。则一元多项式可写成一下形式:
其中,
若用一个长度为
则可唯一确定多项式
多项式链表创建算法如下:
/**
* 创建多项式链表
* @param ele coef: 系数; expn: 指数
*/
export function createPolynList(ele: { coef: number; expn: number }[]) {
const list = new List<{ coef: number; expn: number }>()
list.length = ele.length
ele.forEach((e) => {
const newNode = new ListNode(e)
let prev = list.headNode.next
let tmp = list.headNode
while (prev && newNode.data!.expn > prev.data!.expn) {
tmp = prev
prev = prev.next
}
newNode.next = prev
tmp.next = newNode
})
return list
}多项式的次数可能很高且变化很大 ↩︎