您的位置:首页 > 理论基础 > 数据结构算法

数据结构题集(严蔚敏版)题目——第二章 线性表

2014-10-18 18:35 218 查看
数据结构题集(严蔚敏版)题目——第二章 线性表题目选作。带星号的题基本上全都包含了,没带星号的题选作了大部分。

题目汇总:

/**
 1、设顺序表va中得数据元素递增有序,试写一算法,将x插入到顺序表的适当位置上,以保持该表的有序性
 */
void InsertElemToOrderedTable(SqList *list, int x);

/**
 2、设A=(a1,...am)和B=(b1,...bm)均为线性表,A`和B`分别为A、B中除去最大共同前缀后的子表,
 若A`B`均为空表,则A=B;若A`为空表而B`不是,并且A`的首元小于B`的首元,则A<B,否则为B<A
 试写一个比较A、B大小的算法,不能破坏原表A、B,也不一定先求得A`B`才进行比较
 */
void CompareTwoTable(SqList listA, SqList listB);
/**
 3、已知指针ha和hb分别指向两个单链表的头结点,并且两个链表的长度分别为m和n,试写一算法将这两个链表连接在一起
 */
void UnionTwoLinkList(LinkList ha, LinkList hb, int m, int n);
/**
 4、la和lb为两个无头单链表,从la中删除自第i个元素起len个元素并插入到lb的第j个元素之前,若lb中只有j-1个元素。则插在表尾
 #warning:由于该LinkList封装时为带头指针的链表,故无法正常运行,仅供参考算法。
 */
Status DeleteElemsAndInsertToAnotherList(LinkList la, LinkList lb, int i, int len, int j);
/**
 5、已知线性表中元素以值递增有序排列,并以单链表做存储结构,试写一高效算法删除表中所有值大于mink且小于maxk的元素(若存在)。
 要求释放被删除结点空间。mink和maxk是两个给定的参数,其值可以与表中元素相同,也可以不同
 */
Status DeleteElemsBetweenMinkAndMaxk(LinkList list, int mink, int maxk);
/**
 6、试写一算法,实现单链表的就地逆置,即利用原表的存储空间将线性表(a1...an)逆置为(an...a1)
 */
void ReverseLinkList(LinkList list);
/**
 7、试写一算法,实现顺序表的就地逆置
 */
void ReverseSqList(SqList *list);
/**
 8、设线性表A=(a1,a2...am),B=(b1,b2...bn),试写一算法按如下规则合并AB为C
 C=(a1,b1...am,bm,bm+1...bn)当m≤n时
 或C=(a1,b1...an,bn,an+1...am)当m>n时
 注意,要求利用原表(A表和B表)构建C表,且mn并未显式存储
 */
void UnionTwoLinkListAlternately(LinkList listA, LinkList listB);
/**
 9、有两个递增单链表,编写算法将两表归并成递减的表C要求利用原表。
 */
void UnionTwoLinkListDecrease(LinkList listA, LinkList listB);
/**
 10、两个递增的表A、B,求A与B的交集,要求:(1)、利用A表存放最终结果,
 (2)、求得的结果依旧递增,(3)、A、B中可能存在值相同的元素,但最终交集中不能有相同元素。
 */
void IntersectionTwoSqList(SqList *listA, SqList *listB);
/**
 11、上一题的链表形式
 */
void IntersectionTwoLinkList(LinkList *listA, LinkList *listB);
/**
 12、已知A,B和C是三个递增有序线性表,对A作如下操作:删去既在B中出现又在C中出现的元素,对顺序表编写实现上述操作的算法。
 注意:题目中没有特别指明同一表中的元素值各不相同
 */
void DeleteSameElemsInOtherTwoSqList(SqList *listA, SqList *listB, SqList *listC);
/**
 13、同上一题,对单链表编写算法,释放A表中无用的结点空间
 */
void DeleteSameElemsInOtherTwoLinklist(LinkList *listA, LinkList *listB, LinkList *listC);
/**
 14、已知由一个线性链表表示的线性表中含有三种字符的数据元素(字母、数字和其他字符),
 试编写算法将该链表分割为三个循环链表,每个循环链表中均只有一类字符。
 */
void SegmentTheLinkListToThreeCycleList(LinkList list);
/**
 15、设以带头结点的双向循环链表表示的线性表L = (a1, a2...an)。
 试写一时间复杂度为O(n)的算法将L改造为L = (a1,a3...,an,...a4,a2)。
 */
void ChangeTheSequenceOfDoubleCycleLinkList(DoubleLinkList *list);
/**
 16、设一双向循环链表中添加一访问频度域freq,初始化为0,每次进行locate操作后被访问的值的freq加一,
 同时调整结点次序使其按照访问品读非递增顺序排列。试写上述locate算法
 */
typedef struct CDNode{
    struct CDNode *next;
    struct CDNode *prior;
    ElemType data;
    int freq;
}CDNode;

typedef CDNode * CDLinkList;

CDLinkList FreqLocate(CDLinkList *list, ElemType e);


代码实现:

void InsertElemToOrderedTable(SqList *list, int x)
{
    int i;
    for (i = 1; i < list->length; i++) {
        if (x > list->data[i] && x < list->data[i + 1]) {
            ListInsert(list, i + 1, x);
            break;
        }
    }
    if (i == list->length) {
        ListInsert(list, list->length + 1, x);
    }
}

void CompareTwoTable(SqList listA, SqList listB)
{
    SqList sublistA = {{0}, 0}, sublistB = {{0}, 0};
    int i, j, k = 1;
    //忽略共同前缀
    for (i = 1, j = 1; i <= listA.length && j <= listB.length; i++, j++) {
        if (listA.data[i] != listB.data[j]) {
            break;
        }
    }
    //构建A`
    for (; i <= listA.length; i++) {
        ListInsert(&sublistA, k++, listA.data[i]);
    }
    
    //构建B`
    k = 1;
    for (; j <= listB.length; j++) {
        ListInsert(&sublistB, k++, listB.data[j]);
    }
    
    printf("表A\n");
    for (int m = 1; m <= sublistA.length; m++) {
        printf("%c ", sublistA.data[m]);
    }
    printf("\n表B\n");
    for (int m = 1; m <= sublistB.length; m++) {
        printf("%c ", sublistB.data[m]);
    }
    printf("\n");
    
    if (sublistA.length == 0 && sublistB.length == 0) {
        printf("equal\n");
    } else if (sublistA.length == 0 || (sublistB.length > 0 && sublistA.data[1] < sublistB.data[1])) {
        printf("A < B\n");
    } else {
        printf("A > B\n");
    }
}

void UnionTwoLinkList(LinkList ha, LinkList hb, int m, int n)
{
    Node *p, *q;
    if (m < n) {
        p = ha;
        q = hb;
    } else {
        p = hb;
        q = ha;
    }
    
    while (p->next != NULL) {
        p = p->next;
    }
    p->next = q->next;
    free(q);
}

//本题中所有return INFEASIBLE的判断块均为看答案后改正的
Status DeleteElemsAndInsertToAnotherList(LinkList la, LinkList lb, int i, int len, int j)
{
    if (i < 0 || j < 0 || len < 0) {
        return ERROR;
    }
    int k = 1;
    Node *p, *q, *r, *prior = NULL;
    p = la;
    
    //找到第i个元素
    while (p && k < i) {
        prior = p;
        p = p->next;
        k++;
    }
    
    if (!p) {
        return INFEASIBLE;
    }
    
    //找到i个元素后第len个元素
    k = 1;
    q = p;
    while (q && k < len) {
        q = q->next;
        k++;
    }
    
    if (!q) {
        return INFEASIBLE;
    }
    
    //在la中进行删除操作
    if (prior == NULL) {    //当i等于1时,改变la的首元素为q的下一个元素
        la = q->next;
    } else {
        prior->next = q->next;
    }
    
    //在lb中进行连接操作
    if (j == 1) {           //当j等于1时将la中得元素插入到lb之前,重新定位lb为p
        q->next = lb;
        lb = p;
    } else {
        k = 1;
        r = lb;
        while (r && k < j - 1) {
            r = r->next;
        }
        
        if (!r) {
            return INFEASIBLE;
        }
        
        q->next = r->next;
        r->next = p;
    }
    
    return OK;
}

Status DeleteElemsBetweenMinkAndMaxk(LinkList list, int mink, int maxk)
{
    if (list == NULL) {
        return ERROR;
    }
    
    Node *priorA = NULL, *priorB, *p, *q;
    p = list->next;
    while (p && p->data < mink) {
        priorA = p;
        p = p->next;
    }
    
    q = p;
    while (q && q->data <= maxk) {
        priorB = q;
        q = q->next;
    }
    
    priorA->next = q;
    
    Node *r;
    while (p != q) {
        r = p;
        p = p->next;
        free(r);
    }
    
    return OK;
}

//答案给出的是头插法
void ReverseLinkList(LinkList list)
{
    Node *p, *q, *r;
    //如果表不存在
    if (list == NULL) {
        return;
    }
    p = list->next;
    //如果表为空表
    if (p == NULL) {
        return;
    }
    q = p->next;
    //如果只有一个元素
    if (q == NULL) {
        return;
    }
    r = q->next;
    
    p->next = NULL;
    //为了将最后一个元素也逆置,需要判定的是q,最后将头指针指向p即可
    while (q != NULL) {
        q->next = p;
        p = q;
        q = r;
        if (r != NULL) {
            r = r->next;
        }
    }
    list->next = p;
}

void ReverseSqList(SqList *list)
{
    int start, end, temp;
    for (start = 1, end = list->length; start < end; start++, end--) {
        temp = list->data[start];
        list->data[start] = list->data[end];
        list->data[end] = temp;
    }
}

void UnionTwoLinkListAlternately(LinkList listA, LinkList listB)
{
    int count = 0;
    Node *p, *q, *r;
    LinkList listC = (Node *)malloc(sizeof(Node));
    listC->next = listA->next;
    p = listA->next;
    q = listB->next;
    r = listC->next;
    while (p != NULL && q != NULL) {
        if (count % 2 == 0) {
            p = p->next;
            r->next = q;
        } else {
            q = q->next;
            r->next = p;
        }
        r = r->next;
        count++;
    }
    
    PrintLinkList(listC);
}

void UnionTwoLinkListDecrease(LinkList listA, LinkList listB)
{
    Node *p, *q, *r;
    LinkList listC = (Node *)malloc(sizeof(Node));
    p = listA->next;
    q = listB->next;
    r= listC;
    while (p != NULL && q != NULL) {
        if (p->data < q->data) {
            r->next = p;
            r = r->next;
            p = p->next;
        } else {
            r->next = q;
            r = r->next;
            q = q->next;
        }
    }
    
    if (p == NULL) {
        r->next = q;
    } else if (q == NULL) {
        r->next = p;
    }
    
    ReverseLinkList(listC);
    PrintLinkList(listC);
}

void IntersectionTwoSqList(SqList *listA, SqList *listB)
{
    int i, j, k = 1;
    
    for (i = 1; i <= (*listA).length;) {
        for (j = 1; j <= (*listB).length;) {
            
            if ((*listA).data[i] == (*listA).data[i - 1]) {
                i++;
                continue;
            } else if ((*listB).data[j] == (*listB).data[j - 1]) {
                j++;
                continue;
            }
            
            if ((*listA).data[i] == (*listB).data[j]) {
                (*listA).data[k++] = (*listA).data[i];
                i++;
                j++;
            } else if ((*listA).data[i] < (*listB).data[j]) {
                i++;
            } else {
                j++;
            }
        }
    }
    (*listA).length = k - 1;
    for (i = 1; i < k; i++) {
        printf("%d ", (*listA).data[i]);
    }
    printf("\n");
}

#warning - 网上学习的
void IntersectionTwoLinkList(LinkList *listA, LinkList *listB)
{
    //prior用于记录前驱指针
    LinkList pa = (*listA)->next, pb = (*listB)->next, priorA = (*listA), priorB = (*listB);
    LinkList temp;
    
    //因为是求交集,所以当pa与pb的data不相等时删除该结点
    while (pa && pb) {
        if (pa->data < pb->data) {
            temp = pa;
            pa = pa->next;
            priorA->next = pa;
            free(temp);
        } else if (pa->data > pb->data) {
            temp = pb;
            pb = pb->next;
            priorB ->next = pb;
            free(temp);
        } else {
            //相等时判定,因为A中可能有相同元素,所以应该删除这些相同元素
            //B是不用判定的,因为接下来的比较中会将重复元素删除
            if (pa->data == priorA->data) {
                temp = pa;
                pa = pa->next;
                priorA->next = pa;
                free(temp);
            } else {
                priorA = pa;
                pa = pa->next;
            }
        }
    }
    
    //处理A或B表的剩余结点
    while (pa) {
        temp = pa;
        pa = pa->next;
        priorA->next = pa;
        free(temp);
    }
    while (pb) {
        temp = pb;
        pb = pb->next;
        priorB->next = pb;
        free(temp);
    }
    
    pb = (*listB);
    free(pb);
}

void DeleteSameElemsInOtherTwoSqList(SqList *listA, SqList *listB, SqList *listC)
{
    //2 2 3 5 5 7 8 11 13
    IntersectionTwoSqList(listB, listC);
    int i = 1, j = 1;
    int e;
    while (i <= (*listA).length && j <= (*listB).length) {
        if ((*listA).data[i] < (*listB).data[j]) {
            i++;
        } else if ((*listA).data[i] > (*listB).data[j]) {
            j++;
        } else {
            ListDelete(listA, i, &e);
        }
    }
}

void DeleteSameElemsInOtherTwoLinklist(LinkList *listA, LinkList *listB, LinkList *listC)
{
    IntersectionTwoLinkList(listB, listC);
    
    LinkList p = (*listA)->next, q = (*listB)->next, temp;
    int cur = 1, e;
    while (p && q) {
        if (p->data < q->data) {
            cur++;
            temp = p;
            p = p->next;
            free(temp);
        } else if (p->data > q->data) {
            temp = q;
            q = q->next;
            free(temp);
        } else {
            LinkListDelete(listA, cur, &e);
        }
    }
}

void SegmentTheLinkListToThreeCycleList(LinkList list)
{
    LinkList listA, listB, listC;       //此处应该定义为循环链表
    LinkList p = list->next;
    
    int i = 1, j = 1, k = 1;
    //三类字符,数字、字母和其他
    while (p) {
        if (isalpha(p->data)) {
            LinkListInsert(&listA, i++, p->data);
        } else if (isnumber(p->data)) {
            LinkListInsert(&listB, j++, p->data);
        } else {
            LinkListInsert(&listC, k++, p->data);
        }
        p = p->next;
    }
}

void ChangeTheSequenceOfDoubleCycleLinkList(DoubleLinkList *list)
{
    //此算法使用的数据结构应该为双向循环链表,此处仅以双向链表代替
    DoubleLinkList p = (*list)->next;
    DoubleLinkList oddList, evenList;
    
    int count = 1, k = 1;
    while (p) {                                             //此处应为循环链表的判尾条件
        if (count % 2 == 0) {
            DLinkListInsert(&evenList, 1, p->data);         //偶数逆序插入
        } else {
            DLinkListInsert(&oddList, k++, p->data);        //奇数顺序插入
        }
        count++;
    }
    //联接两双向链表,用list记录返回
    ConcatTowDLinkList(&oddList, &evenList, list);
}

CDLinkList FreqLocate(CDLinkList *list, ElemType e)
{
    CDLinkList p = (*list)->next;   //查找返回的结点
    CDLinkList q = p;               //比较优先级用
    
    //1、定位
    while (p != *list) {
        if (p->data == e) {
            break;
        }
        p = p->next;
    }
    if (p == *list) {
        return NULL;
    }
    
    //2、增加freq
    p->freq++;
    
    //3、删除结点
    p->prior->next = p->next;
    p->next->prior = p->prior;
    
    //4、查找合适的位置
    while (q != *list && p->freq < q->freq) {
        q = q->next;
    }
    
    //5、插入到q结点之前
    p->next = q;
    p->prior = q->prior;
    q->prior->next = p;
    q->prior = p;
    
    return p;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: