408(1)——线性表

一、线性表

1.1顺序表

1、删除最小的元素,空出的元素由最后一位填补

bool Del_Min(SqList &L, ElemType &value){
    if(L.length == 0)
        return false;
    value == L.data[0];
    int pos = 0;
    for(int i = 1; i < L.length; i++)
        if(L.data[i] < value){
            value = L.data[i];
            pos = i;
        }
    L.data[pos] = L.data[L.length-1];
    L.length--;
    return true;
}

2、所有元素逆置

void Reverse(SqList &L){
    ElemType temp;
    for(int i = 0; i < L.length/2; i++){
        temp = L.data[i];
        L.data[i] = L.data[L.length-i-1];
        L.data[L.length-i-1] = temp;
    }
}

3、删除所有值为x的元素,时间复杂度为O(n),空间复杂度为O(1)

void Del_X_1(SqList &L, ElemType x){
    int k = 0;
    for(int i = 0; i < L.length; i++)
        if(L.data[i] != x)
            L.data[k++] = L.data[i];
    L.length=k;         
}

void Del_X_2(SqList &L, Elemtype x){
    int k = 0, i = 0;
    while(i < L.length){
        if(L.data[i] == x)
            k++;
        else
            L.data[i-k] = L.data[i];
    }
    L.length -= k;
}

4、从有序表中删除其值在给定值s与t之间的所有元素(s<t)

bool Del_s_t(SqList &L, ElemType s, ElemType t){
    int i, j;
    if(s >= t || L.length == 0)
        return false;
    for(i = 0; i < L.length&& L.data[i] < s; i++);
    if(i >= L.length)
        return false;
    for(j = i; j < L.length&&L.data[i] < t; j++);
    for(;j < L.length; i++, j++)
        L.data[i] = L.data[j];
    L.length = i;
    return true;
}

5、顺序表中删除其值在给定值s与t之间的所有元素(包括s和t)

void Del_s_t2(SqList &L, ElemType s, ElemType t){
    if(s > t || L.length == 0)
        return false;
    int k = 0;
    for(int i = 0; i < L.length; i++){
        if(L.data[i] >= s && L.data[i] <= t)
            k++;
        else
            L.data[i-k] = L.data[i];
    }
    L.length -= k;
    return true;
}

6、有序顺序表中删除所有值重复的元素

bool Del_Repeat_Value(SqList &L){
    if(L.length == 0)
        return false;
    int i=0, j=1;
    for(;j<L.length;j++){
        if(L.data[i] != j)
            L.data[++i] = L.data[j];
    }
    L.length = i+1;
    return true;
}

7、将两个有序顺序表合并为一个

bool Merge(SqList &A, SqList &B, SqList &C){
    if(A.length + B.length > C.MaxSize)
        return false;
    int i = 0, j = 0, k = 0;
    while(i < A.length && j < B.length){
        if(A.data[i] <= B.data[j])
            C.data[k++] = A.data[i++];
        else
            C.data[k++] = B.data[j++];
    }
    while(i < A.length){
        C.data[k++] = A.data[i++];
    }
    while(j < B.length){
        C.data[k++] = B.data[j++];
    }
    C.length = k;
    return true;
}

8、将数组A[m+n]中的两个线性表(a1,a2,…,am)和(b1,b2,…,bm)位置互换变为(b1,b2,…,bm)和(a1,a2,…,am)

//使用2中的Reverse函数分别对线性表a、b以及A转换即可

9、用最短的时间在顺序表中查找x,并且与后面一个元素互换位置,找不到就插入表中使其任然有序

void SearchExchangeInsert(SqList &L, ElemType x){
	int low = 0, high = L.length - 1, mid;
    while(low <= high){
        mid = (low+high)/2;
        if(A[mid] == x)
            break;
        else if(A[mid] < x)
            low = mid + 1;
        else
            high = mid - 1;
    }
    if(A[mid] == x && mid != n-1)
        t=A[mid];
    	A[mid]=A[mid+1];
    	A[mid+1]=t;
    if(low > high){
        for(i=n-1;i>high;i++)
            A[i+1] = A[i];
        A[i+1] = x;
    }
}

10、

//与第八题思路一致,时间复杂度O(n),空间复杂度O(1)

11、寻找两个升序序列的中位数

//1、分别寻找两个序列的中位数a和b
//2、如果a < b,那么舍弃a左边那部分(因为a左边比a小,那么左边<a<b,中位数必然不会出现在两个序列合并后的a的左半边),舍弃b右边那部分(同理,中位数也不会出现在两个数列合并后的b的右半边,因为偏右)

12、

/*
①选取候选的主元素。依次扫描所给数组中的每个整数,将第个遇到的整数 Num保存到
C中,记录Num的出现次数为1;若遇到的下一个整数仍等于Num, 则计数加1,否则
计数减1;当计数减到0时,将遇到的下一个整数保存到c中,计数重新记为1,开始
新一轮计数,即从当前位置开始重复上述过程,直到扫描完全部数组元素。
②判断c中元素是否是真正的主元素。再次扫描该数组,统计C中元素出现的次数,若大
于n/2,则为主元素:否则,序列中不存在主元素。
*/

13、空间换时间,设置辅助数组,检查没有出现的元素

1.2链表

1、设计递归算法,删除不带头节点的单链表L中所有值为x的节点

void Del_x(LinkList &L, ElemType x){
    LNode *p;
    if(L==NULL)
        return;
    if(L->data==x){
        p=L;
        L=L->next;
        free(p);
        Del_x(L,x);
    }
    else
        Del_x(L->next,x);
}

2、在带头结点的单链表L中,删除所有值为x的节点,并释放其空间

void Del_x_1(LinkList &L, ElemType x){
    if(L->next == NULL)
        return;
     LNode *p = L->next, *prep = L;
    while(p!=NULL){
        if(p->data == x){
            LNode *q = p;
            prep->next=p->next;
            p = p->next;
            free(q);
        }
        else{
            prep = p;
            p = p->next;
        }
    }
}

3、L为带头结点的单链表,编写算法实现从尾到头反向输出每个节点的值

void Reverse_Print(LinkList &L){
    LNode *p = L->next;
    if(p->next != NULL)
        Reverse_Print(p->next);
    else
        print(p->data);
}

4、删除带头结点的单链表L中值最小的结点的高效算法

//minPrep,minvalue存储当前搜索过的所有节点中最小的值以及其前驱节点,prep和p存储当前结点以及前驱结点,整个单链表过一遍之后,用minPrep
//删除最小结点
void Del_Min(LinkList &L){
    LNode *minPrep = L, *prep = L, *p = L.next;
    ElemType minValue = p->data;
    while(p!=NULL){
        if(p->data<minalue){
            minPrep = prep;
            minValue = p->data;
        }
        prep = p;
        p = p->next;
    }
    minPrep->next = minPrep->next->next;
}

5、将带头结点的单链表就地逆置

//采用头插法建立单链表,然后遍历新的单链表
void Reverse(LinkList &L){
    LNode *p = L->next, *q = p->next;
    while(p!=NULL){
        p->next = L->next;
        L.next = p;
        p = q;
        if(q!=NULL)
            q = q->next;//处理最后一个节点,防止空指针异常
    }
}

6、带头结点单链表L,设计算法使其元素递增有序

//遍历一遍放到数组中,快速排序,再放到单链表中O(nlog2n)
//直接插入排序思想O(n2)

7、删除无序单链表内值处于给定区间内的结点

//设置prep和p,如果p的值在区间内,就用prep删除p结点
void Del_Range_Value(LinkList &L, ElemType s, ElemType t){
    LNode *prep = L, *p = L->next;
    while(p != NULL){
        if(p->data > s && p->data < t){
            p = p->next;
            prep->next = p;
        }
        else{
            prep = p;
            p = p->next;
        }
    }
}

8、找出两个给定单链表的公共节点

//第一个结点相同之后,之后的结点必然相同
LNode Find_Common-LNode(LinkList &A, LinkList &B){
    int numA = 0, numB = 0;
    LNode *pNodeA = A, *pNodeB = B;
    while(pNodeA != NULL){
        numA++;
        pNodeA = pNodeA->next;
    }
    while(pNodeB != NULL){
        numB++;
        pNodeB = pNodeB->next;
    }
    *pNodeA = A, *pNodeB = B;
    if(numA > numB){
        int count = numA-numB;
        while(count != 0){
            if(pNodeA == pNodeB)
                return pNodeA;
            else{
                pNodeA = pNodeA->next;
            	pNodeB = pNodeB->next;
            }
        }
        return NULL;
    }
    if(numA < numB){
        int count = numB-numA;
        while(count != 0){
            if(pNodeA == pNodeB)
                return pNodeA;
            else{
                pNodeA = pNodeA->next;
            	pNodeB = pNodeB->next;
            }
        }
        return NULL;
    }
}

9、按递增次序输出带头结点单链表中各节点的数据

//根据第6题排序之后再输出

10、将单链表A分成两个带头单链表A和B,使A中含有原链表中序号为奇数的元素,B中含有原链表中序号为偶数的元素

//设置计数器count,判断当前节点序号是偶数还是奇数
void Devide_List(LinkList &A, LinkList &B){
    LNode *prep=A, *p = A->next, *b = B, *q;
    int count = 0;
    while(p!=NULL){
        count++;
        if(count%2!=0){
            prep = p;
            p = p->next;
        }
        else{
            q = p;
            prep->next = p->next;
            p = p->next;
            //尾插法
            q->next = b->next;
            b->next = q;
            b = q;
        }
    }
}

11、设计就地算法将{a1,b2,…,an,bn}拆分为{a1,a2,…,an}和{bn,…,b2,b1}

//按照第10题的思路,a序列采用尾插法建立单链表,b序列采用头插法建立单链表
void Devide_List(LinkList &A, LinkList &B){
    LNode *prep=A, *p = A->next, *q;
    int count = 0;
    while(p!=NULL){
        count++;
        if(count%2!=0){
            prep = p;
            p = p->next;
        }
        else{
            q = p;
            prep->next = p->next;
            p = p->next;
            //头插法
            q->next = B->next;
            B->next = q;
        }
    }
}

12、删除递增有序的单链表中的重复值的元素

//设置prep和p,prep指向当前已经搜索过的没有重复元素的最后一个,p向后寻找,如果当前元素的值和prep不相同,则prep->next=p;p=p->next;
//如果相同p向后寻找,直到p==NULL
void Del_Repeat_Value(LinkList &L){
    LNode *prep = L->next, p = prep->next;
    while(p!=NULL){
        if(prep->data == p->data){
            LNode *q = p;
            p = p->next;
            prep->next = p;
            free(q);
        }
        else{
            prep = p;
            p = p->next;
        }
    }
}

13、将两个元素递增的线性表合并成一个元素递减的线性表

//同时比较大小,小的使用头插法插入,最后剩余的再使用头插法
void Combine_List(LinkList &A, LinkList &B, LinkList &C){
    LNode *pa = A->next, pb = B->next, *q;
    while(pa&&pb){
        if(pa->data<=pb->next){
            q = pa;
            pa = pa->next;
            q->next = C->next;
            C->next = q;
        }
        if(pa->data>pb->next){
            q = pb;
            pb = pb->next;
            q->next = C->next;
            C->next = q;
        }
    }
}

14、A和B是两个带头结点的单链表,其中元素递有序,设计算法从A和B中产生单链表C,不破坏A和B的结点

void Get_Common(LinkList &A, LinkList &B, LinkList &C){
    LNode *pa = A->next, *pb = B->next, *pc = C, *r;
    while(pa&&pb){
        if(pa<pb)
            pa = pa->next;
        else if(pa>pb)
            pb=pb->next;
        else{
            r = (LNode *)malloc(sizeof(LNode));
            r->data = pa->data;
            pc->next = r;
            pc = r;
            pa = pa->next;
            pb = pb->next;
        }
    }
    pc->next = NULL;
}

15、已知两个链表A和B分别表示两个集合,其元素递增排列。编制函数,求A与B的交集,并存放于A链表中。

void Get_Common_1(LinkList &A, LinkList &B){
    LNode *pa = A->next, *pb = B->next, *s, pc = A;
    while(pa&&pb){
        if(pa->data<pb->data){
            s = pa;
            pa = pa->next;
            free(s);
        }
        else if(pa->data>pb->data){
            s = pb;
            pb = pb->next;
            free(s);
        }
        else{
            pc->next = pa;
            pc = pa;
        	pa = pa->next;
            s = pb;
            pb = pb->next;
            free(s);
        }
	}
    while(pa){
        s = pa;
        pa = pa->next;
        free(s);
    }
    while(pb){
        s = pb;
        pb = pb->next;
        free(s);
    }
}

16、两个整数序列A=a1,a2, a3,…,am和B=b1, b2, b3,…, bn已经存入两个单链表中,设计一个算法,判断序列B是否是序列A的连续子序列。

bool Is_Pattern(LinkList &A, LinkList &B){
    LinkList *pa = A->next, *pb = A->next, *pr;
    while(pa&&pb){
        if(pa->data != pb->data)
            pa = pa->next;
        if(pa->data == pb->data){
            pr = pa;
            pa = pa->next;
            pb = pb->next;
            pr = pa;
            while(pa&&pb){
                if(pa->data!=pb->data){
                    pa = pr;
                    pb = A->next;
                    break;
                }
                else{
                    pa = pa->next;
                    pb = pb->next;
                }
            }
            if(!pa&&pb)
                return false;
            return true;
        }
    }
}

17、设计一个算法用于判断带头结点的循环双链表是否对称。

bool Is_Symmetry(DLinkList &L){
    LNode *p = L->next;
    int count = 1;
    while(p != L){
        count++;
    }
    LNode *left = L->prior, *right = L->next;
    if(count%2==0){
        while((count/2)--){
            if(left->data == right->data){
                left = left->prior;
            	right = right->next;
            }
            else{
                break;
            }
        }
        return true;
    }
    else{
        while(left!=right){
            if(left->data == right->data){
                left = left->prior;
            	right = right->next;
            }
            else{
                break;
            }
        }
    }
}

18、有两个循环单链表,链表头指针分别为h1和h2,编写一个函数将链表h2链接到链表h1之后,要求链接后的链表仍保持循环链表形式。

LinkList Combine(LinkList &h1, LinkList &h2){
    LNode *p = h1, *q = h2;
    while(p->next){
        p = p->next;
    }
    p->next = h2;
    while(q->next){
        q = q->next;
    }
    q->next = h1;
    return h1;
}

19、设有一个带头结点的循环单链表,其结点值均为正整数。设计一个算法,反复找出单链表中结点值最小的结点并输出,然后将该结点从中删除,直到单链表空为止,再删除表头结点。

void Print_Min_Value(LinkList &L){
    while(L->next!=L){
        LNode *p = L->next, *minPrep = L;
    	int minValue = L->next->data;
        while(p->next!=L){
            if(p->next->data<minValue){
                minPrep = p;
                minValue = p->next->data;
            }
        }
        LNode *s = minPrep->next;
        minPrep->next = minPrep->next->next;
        print(s->data);
        free(s);
    }
    free(L);
}

20、设头指针为L的带有表头结点的非循环双向链表,其每个结点中除有pred(前驱指针)、data (数据)和next (后继指针)域外,还有一个访问频度域freq。在链表被启用前,其值均初始化为零。每当在链表中进行一次Locate (L,x)运算时,令元素值为x的结点中freq域的值增1,并使此链表中结点保持按访问频度非增(递减)的顺序排列,同时最近访问的结点排在频度相同的结点前面,以便使频繁访问的结点总是靠近表头。试编写符合.上述要求的Locate(L,x)运算的算法,该运算为函数过程,返回找到结点的地址,类型为指针型。

LNode Locate(LinkList &L, ElemType x){
    LNode *p = L->next;
    while(p!=NULL){
        if(p->data == x){
            p->freq+=1;
        } 
    }
    if(p==NULL)
        return NULL;
    LNode *s = p;
    p = p->pred;
    p->next = s->next;
    while(p!=L){
        if(p->freq>s->freq){
            s->next = p->next;
            p->next->pred = s;
            p->next = s;
            s->pred = p;
        }
    }
    if(p==L&&s->next==NULL&&s->pred==NULL){
        s->next = L->next;
        L->next->pred = s;
        L-next = s;
        s->pred = L;
    }
    return s;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值