1. 根据一维数组中的n个元素建立一个有序线性表。
解:因为要新建线性表,所以考虑用链表而不是顺序表,否则需要频繁地移动表中元素。
Status ConstructList(LinkList &L,ElemType a[n]) {
LinkListp, q, pre;
L =(LinkList)malloc(sizeof(LNode)); //生成头结点
if (!L)exit(OVERFLOW);
p = (LinkList)malloc(sizeof(LNode)); //生成开始结点
if (!p)exit(OVERFLOW);
p->data = a[0]; p->next = NULL;
L->next = p; //此时,L是只有一个头结点和开始结点单链表
for (int i = 1; i < n; i ++) {
pre = L;
q = L->next; //每次插入新结点时均从开始结点扫描
while (q != NULL) {
if (q->data <a[i]) {
pre = q;
q = q ->next;
}
else { //找到插入位置(非表尾)
p = (LinkList)malloc(sizeof(LNode)); //生成新插入结点
if (!p) exit(OVERFLOW);
p->data = a[i];
p->next= q;
pre->next = p;
break; //继续插入下一个元素
}
}
if (q == NULL) {
p =(LinkList)malloc(sizeof(LNode)); //生成新结点,插入表尾
if(!p) exit(OVERFLOW);
p->data =a[i]; p->next = q;
pre->next = p;
}
}
return OK;
}
2. 设计一个算法,将一个顺序表重新排列成以第一个结点为界的两部分,前一部分的数据元素的值均小于第一个结点中数据元素的值,后一部分元素的值均大于或等于第一个结点中数据元素的值。要求:该算法所采用的额外存储空间为O(1)。
解:让某个变量a等于顺序表的第一个结点的数据元素的值。然后从左向右扫描找到大于等于a的元素,从右向左扫描,找到小于a的元素,将它们进行交换,直到整个表扫描完成为止。注意:下面的算法只是将所有结点分成按要求的两部分,但是最后并没有将第一个结点“物理上”放置在这两部分中间,该结点仍然是第一个结点。
Status partition(SeqList&L) {
int i = 0, j = L.length – 1;
ElemType a = L.data[0], temp;
while (i < j) {
while (i < j &&L.data[i] < a) i ++; // i最后指向大于等于a的元素
while (i < j && L.data[j]>= a) j --; //j 最后指向小于a的元素
if (i < j) {
temp =L.data[i]; //交换i、j所指向的元素
L.data[i]=L.data[j];
L.data[j]=temp;
}
}
return OK;
}
3. 编写一个算法将带头结点的单链表中值重复的结点删除,使所得的结果表中各结点的值均不相同。
解:由于单链表不一定有序,所以对于每个结点*p,从其后开始直到链表末尾扫描,判断是否存在与之值域相等的结点,若有,删除之。对应的算法如下:
Status DelelteList(LinkList &L) {
LinkList p= L->next, q, pre, r;
while (p!=NULL) {
q= p->next; pre = p;
while (q!=NULL) {
if(q->data == p->data) { //若有重复结点,删除
r= q;
pre->next = q->next;
q = q->next;
free(r);
}
else { //若无,继续扫描剩余结点
pre = q;
q=q->next;
}
}
p=p->next;
}
return OK;
}
4. 编写一个算法,逆置一个带头结点的双向链表L。
解:将原来的双向链表一分为二,前一个链表由原来的头结点和开始结点组成,后一个链表由原来的双向链表中的剩余结点组成。然后依次从第二个链表中抽取出第一个结点插入到第一个链表的后结点之后。
(非循环双向链表:头结点的prior域为NULL,终端结点的next域为NULL)
StatusReverseDList(DLinkList &DL) {
DLinkList p, q;
if (DL->next != NULL) {//DL是一个非空表
p = DL->next->next,
DL->next->next = NULL; //原来的开始结点变成终端结点,其next
//域应为NULL
while(p!=NULL) {
q = p->next; //q用来保存下一个待插入结点的地址
p->next = DL->next;
DL->next->prior= p;
DL->next = p;
p->prior = DL;
p = q; //p将指向下一个待插入结点
}
}
return OK;
}
(循环双向链表:头结点的prior域指向终端结点,终端结点的next域指向头结点)
StatusReverseDList(DLinkList &DL) {
DLinkListp, q;
if(DL->next != NULL) {//DL是一个非空表
p= DL->next->next,
DL->next->next= DL; //原来的开始结点将变成终端结点,其next域
//应指向头结点
DL->prior->next = NULL; //为了保证下面while循环能终止
DL->prior = DL->next; //头结点的prior域应该指向开始结点
while (p!=NULL) {
q= p->next; //q用来保存下一个待插入结点的地址
p->next= DL->next;
DL->next->prior= p;
DL->next = p;
p->prior = DL;
p =q; //p将指向下一个待插入结点
}
}
returnOK;
}