七、有序表
线性表中所有元素以递增或递减方式有序排列的线性表称为有序表。
在一个具有n个结点的有序单链表中插入一个新结点后,仍然保持有序的时间复杂度是O(n)。(扫描的过程是一个线性阶的时间复杂度O(n),插入的操作是一个常量阶的时间复杂度O(1),线性阶加常量阶的结果仍为线性阶)
- 有序表的归并算法(二路归并)
//顺序表归并(需要开辟一个新空间存储归并后的新表)
void mergearray(int a[], int m,int b[], int n,int c[])//传入三个数组,前两个存初始的两个线性表,另一个存结果线性表,还有两个整型变量来指出初始两个线性表的长度,归并后的新表显然是前两个线性表长度之和
{
int i=0,j= 0;
int k=0;//需要一个下标始终表示当前新表的尾部
while (i <m &&j<n)
{
if (a[i] < b[j])
c[k++] = a[i++]; //c[k] = a[i];k++;i++;
else
c[k++] = b[j++];
}
while (i < m)
c[k++] = a[i++];
while (j < n)
c[k++] = b[j++];
}
//链表归并之同序(不需要开辟新空间,只需要挪动指针)
void merge(LNode *A, LNode *B, LNode *&C) //传入三个链表的头指针,A、B这两个头指针是不需要发生改变的,所以不需要用引用型;而对于C是一个需要指向新链表头结点的指针,所以需要对指针用引用型
{
LNode *p = A->next;
LNode *q = B->next;
LNode *r; //需要一个指针始终指向当前得到链表的尾部
C=A; //C指向A链表的头结点
C->next = NULL;
free(B); //B链表的头结点就不要了
r=C; //此刻的头结点同时也是尾结点
while(p != NULL && q!= NULL)
{
if(p->data <= q->data)
{
r->next = p; p=p->next;
r = r->next; //让r始终指向新链表的尾部位置
}
else
{
r->next = q; q=q->next;
r = r->next;
}
}
if(p!=NULL) r->next=p; //只需要一个指针就能把剩下的结点归并,不需要用while循环
if(q!=NULL) r->next=q;
}
//链表归并之反序(原来是升序,归并后降序,类似头插法)
void mergeR(LNode *A, LNode *B, LNode *&C) //传入三个链表的头指针,A、B这两个头指针是不需要发生改变的,所以不需要用引用型;而对于C是一个需要指向新链表头结点的指针,所以需要对指针用引用型
{
LNode *p = A->next;
LNode *q = B->next;
LNode *s; //需要一个指针始终指向当前得到链表结点的头部
C=A; //C指向A链表的头结点
C->next = NULL;
free(B); //B链表的头结点就不要了
while(p != NULL && q!= NULL)
{
if(p->data <= q->data)
{
s=p; p=p->next;
s->next=C->next; C->next=s;
}
else
{
s=q; q=q->next;
s->next=C->next; C->next=s;
}
}
while(p!=NULL) //仅修改一个指针已经不能把剩下的结点都归并,需要用到while循环
{
s=p;
p=p->next;
s->next=C->next;
C->next=s;
}
while(q!=NULL)
{
s=p;
q=q->next;
s->next=C->next;
C->next=s;
}
}