2 何时选用顺序表,何时选用链表作为线性表的存储结构合适? 各自的主要优缺点是什么?
在实际应用中,应根据具体问题的要求和性质来选择顺序表或链表作为线性表的存储结构,通常有以下几方面的考虑:
1.基于空间的考虑。当要求存储的线性表长度变化不大,易于事先确定其大小时,为了节约存储空间,宜采用顺序表;反之,当线性表长度变化大,难以估计其存储规模时,采用动态链表作为存储结构为好。
2.基于时间的考虑。若线性表的操作主要是进行查找,很少做插入和删除操作时,采用顺序表做存储结构为宜;反之, 若需要对线性表进行频繁地插入或删除等的操作时,宜采用链表做存储结构。并且,若链表的插入和删除主要发生在表的首尾两端,则采用尾指针表示的单循环链表为宜。
顺序表的主要优点: 没使用指针,不用花费附加开销 ;线性表元素的读写访问非常简洁便利
链表的主要优点:无需事先了解线性表的长度;能够适应经常插入删除内部元素的情况; 允许线性表的长度有很大变化
3 在顺序表中插入和删除一个结点平均需要移动多少个结点? 具体的移动次数取决于哪两个因素?
在等概率情况下,顺序表中插入一个结点需平均移动n/2个结点。删除一个结点需平均移动(n-1)/2个结点。具体的移动次数取决于顺序表的长度n以及需插入或删除的位置i。i越接近n则所需移动的结点数越少。
4 链表所表示的元素是否有序? 如有序,则有序性体现于何处? 链表所表示的元素是否一定要在物理上是相邻的? 顺序表的有序性又如何理解?
有序。有序性体现在通过指针数据元素有序的相连。物理上不一定要相邻。顺序表的有序不仅体现在逻辑结构上有序,而且在物理结构(储存结构)也有序。
5 设顺序表L是递增有序表,试写一算法,将x插入到L中并使L仍是递增有序表。 因已知顺序表L是递增有序表,所以只要从顺序表终端结点(设为i位置元素)开始向前寻找到第一个小于或等于x的元素位置i后插入该位置即可。
在寻找过程中,由于大于x的元素都应放在x之后,所以可边寻找,边后移元素,当找到第一个小于或等于x的元素位置i时,该位置也空出来了。 算法如下:
void InsertIncreaseList( Seqlist *L , Datatype x ) { inti;
if ( L->length>=ListSize) Error(“overflow\
for ( i=L -> length ; i>0 && L->data[ i-1 ] > x ; i--) L->data[ i ]=L->data[ i ] ; // 比较并移动元素 L->data[ i ] =x; L -> length++; }
6 写一求单链表的结点数目ListLength(L)的算法。
由于在单链表中只给出一个头指针,所以只能用遍历的方法来数单链表中的结点个数了。算法如下:
intListLength ( LinkList L ) {
intlen=0 ; ListNode *p;
p=L; //设该表有头结点 while ( p->next ) {
p=p->next; len++; } return len; }
7 写一算法将单链表中值重复的结点删除,使所得的结果链表中所有结点的值均不相同。
本题可以这样考虑,先取开始结点中的值,将它与其后的所有结点值一一比较,发现相同的就删除掉,然后再取第二结点的值,重复上述过程直到最后一个结点。 具体算法:
void DeleteList ( LinkList L ) {
ListNode *p , *q , *s; p=L-next;
while( p->next&&p->next->next) {
q=p;//由于要做删除操作,所以q指针指向要删除元素的直接前趋 while (q->next)
if (p->data==q->next->data)
{s=q->next;q->next=s->next;free(s);//删除与*p的值相同的结点 }
else q=q->next; p=p->next; } }
8 写一算法从一给定的向量A删除值在x到y(x≤y)之间的所有元素(注意:x和y是给定的参数,可以和表中的元素相同,也可以不同)。
voidDeletElem(SqListA,intx,int y) {
ElemType *p,*q; inti=0; int j; p=&A.next;
for(i;i