栈是限定在只能在尾部操作(插入或删除)的线性表。
栈是按照后进先出的,LIFO。
一般来说,栈应该是无上限的,即如果栈满了,应该可以自动扩充。
定义如下的栈结构:
struct Stack
{
int* base;
int* top;
int size;
};
注意,top指向的不是栈顶而是栈顶的下一个元素!
当base==NULL或者top==base时,可以认为栈是空的。
基本操作有push、pop、top(取得栈顶元素但不弹出栈)、isem[......]
栈是限定在只能在尾部操作(插入或删除)的线性表。
栈是按照后进先出的,LIFO。
一般来说,栈应该是无上限的,即如果栈满了,应该可以自动扩充。
定义如下的栈结构:
struct Stack
{
int* base;
int* top;
int size;
};
注意,top指向的不是栈顶而是栈顶的下一个元素!
当base==NULL或者top==base时,可以认为栈是空的。
基本操作有push、pop、top(取得栈顶元素但不弹出栈)、isem[......]
一元多项式的表示及相加:
我们定义P(x)=p0+p1*x+p2*x^2...pn*x^n简写为P=(p0, p1, p2...pn)
再定义Q=(q0, q1, 12...qm)
现在要求R = P(X) + q(X),显然,实际上R=(p0+q0, p1+q1, p2+q2 .. pm+1, pn) 假设m<n。
这种应用场景,用顺序存储不合适,它虽然运算简单,但因为很有可能从1~1000次幂都是0,是稀疏的。因此,链表类似的存储更合适。
首先考虑加法,其[......]
1、循环链表:链表中最后一个结点的指针域指向头结点,整个链表形成一个环。
(1)一般要设置尾指针,方便操作。
(2)从表中任意一个结点出发均可以到达其他任意结点。
(3)两个链表合并为新链表是很方便,只需要把第一个尾指针和第二个的头指针连接起来就好了。
下面是循环链表的基本操作:
2、双向链表:在结点中有两个指针域,一个后继、一个前趋。
(1)特性:d->next->pre == d->pre->next == d
(2)插入、删除时都要操作两个指针[......]
1、线性表也可以用顺序表示实现,即用一组地址连续的存储单元依次存储线性表的数据元素。特点是ai和ai+1位于相邻的存储单元上,只要确定了存储线性表的起始位置,任意元素都可以随机存取。
2、LOC(ai) = LOC(a1)+(i-1)*l
3、通常用数组来描述数据结构中的顺序存储结构。
4、线性表的顺序存储不同于数组的地方是:数组的大小是静态不动的;而线性表类似于C++中的vector,如果存储空间不够,会自动的增加内部空间,而这一切,对外部用户是透明的。
5、顺序存储的[......]
1、链式存储,可以简称链表。
2、链表的一个结点(node)由两部分组成:数据域和指针域。
3、整个链表的存取必须从头指针开始,链表最后一个结点的指针为空,因此它是非随机存取的数据结构。
4、链表中插入结点:假设原结点为p,新结点为s,则:
s->next = p->next;
p->next = s;
不是很难理解吧……
5、基本操作还是比较简单的,下面假定采用无“空头”模式的如下链表:
#define INVALID 0xffff[......]