线性表-链式存储结构及南航学硕专硕编程真题12-18年(只有链表和顺序表)

包含了线性表的基本操作以及南航考研真题的链表操作 12-18年

#include<bits/stdc++.h>
using namespace std;

typedef struct Sqlist {
    int val;
    Sqlist *next;
}*ListNode;

bool InitList(ListNode &listnode)//创建一个空的线性表 
{
    listnode = (ListNode)malloc(sizeof(Sqlist));
    if(!listnode)
    {
        printf("分配失败\n");
        return false;
    }
    listnode->val = -1;
    listnode->next = NULL;
    return true;
}

ListNode SetupList()//给线性表赋值 
{
    ListNode head;
    InitList(head);//创建一个空表 
    ListNode listnode;
    listnode = head;//指向头结点 
    int val,count;
    printf("请输入线性表元素的个数:");
    scanf("%d",&count); 
    printf("请输入线性表的元素:");
    for(int i = 0;i < count;i++)
    {
        scanf("%d",&val);
        listnode->next = (ListNode)malloc(sizeof(Sqlist));
        listnode = listnode->next;
        listnode->val = val;
    }
    listnode->next = NULL;
    return head;
    
}

void DisplayList(ListNode head)//输出链表的所有元素 
{
    ListNode listnode;
    listnode = head;//指向链表头结点    
    while(listnode->next != NULL)
    {
        listnode = listnode->next;
        printf("%d ",listnode->val);
    }    
}

bool DestroyList(ListNode &head)//销毁线性表 
{
    ListNode listnode;
    while(head != NULL)
    {
        listnode = head;
        head = head->next;
        free(listnode);
    }
    head = NULL;
    return true;
}

bool ClearList(ListNode &head)//置线性表为空 
{
    ListNode listnode,tmp;
    listnode = head->next;//从头结点的下一个结点开始 
    tmp = listnode; 
    while(listnode != NULL)
    {
        tmp = listnode;
        listnode = listnode->next;
        free(tmp);
    }
    head->next = NULL;
    return true;
}

bool ListEmpty(ListNode head)//判空 
{
    if(head != NULL && head->next == NULL)
        return true;
    else
        return false;
}

int ListLength(ListNode listnode)//返回数据元素的个数 
{
    int length = 0;
    listnode = listnode->next;//从头结点的下一个结点开始算
    while(listnode != NULL)
    {
        length++;
        listnode = listnode->next;
    } 
    return length;
}

void ListDelete(ListNode &head,int elem)//删除 
{
     ListNode cur,pre;//当前节点和前驱
     cur = head->next;
     pre = head;
     while(cur != NULL)
     {
        if(cur->val == elem)
        {
            ListNode del = cur;
            pre->next = cur->next;
            cur = cur->next;
            free(del);
        }     
        else
        {
            cur = cur->next;
            pre = pre->next;
        }
     }    

bool ListFind(ListNode head,int elem)//在链表中查找某个元素是否存在 
{
    ListNode listnode = head->next;
    while(listnode != NULL)
    {
        if(listnode->val == elem)
            return true;
        else
            listnode = listnode->next;
    }
    return false; 
}

bool Sort_Ascend(ListNode &head)//采用插入排序使线性表非递减 
{
    //先判断是否是空表或者只有一个元素 那么一定是有序的
    if(ListEmpty(head) || ListEmpty(head->next))
        return true;
    ListNode listnode;
    listnode = head->next->next;//从第二个元素开始
    head->next->next = NULL;//断掉原来的链表 
    while(listnode != NULL)
    {
        ListNode tmp = listnode;//取出一个元素 
        listnode = listnode->next;
        ListNode pre = head;//每次判断的头结点
        ListNode cur = head->next;// 需要比较的当前节点 
        while(cur != NULL)
        {
            if(cur->val > tmp->val)//小于当前节点的值则需要插入 
            {
                tmp->next = cur;
                pre->next = tmp;
                break;    
            }    
            else if(cur->next == NULL)//到达链表尾部,插入尾部 
            {
                cur->next = tmp;
                tmp->next = NULL;
                break;
            }
            else
            {
                cur = cur->next;
                pre = pre->next;
            }
        }    
    } 
    return true;
}

bool Sort_Descend(ListNode &head)//采用插入排序使线性表非递增 
{
    //先判断是否是空表或者只有一个元素 那么一定是有序的
    if(ListEmpty(head) || ListEmpty(head->next))
        return true;
    ListNode listnode;
    listnode = head->next->next;//从第二个元素开始
    head->next->next = NULL;//断掉原来的链表 
    while(listnode != NULL)
    {
        ListNode tmp = listnode;//取出一个元素 
        listnode = listnode->next;
        ListNode pre = head;//每次判断的头结点
        ListNode cur = head->next;// 需要比较的当前节点 
        while(cur != NULL)
        {
            if(cur->val < tmp->val)//大于当前节点的值则需要插入 
            {
                tmp->next = cur;
                pre->next = tmp;
                break;    
            }    
            else if(cur->next == NULL)//到达链表尾部,插入尾部 
            {
                cur->next = tmp;
                tmp->next = NULL;
                break;
            }
            else
            {
                cur = cur->next;
                pre = pre->next;
            }
        }    
    } 
    return true;
}

//**************真题分界线 ****************** 

void MergeSort()//17年829和922真题 两个递减合并成递增 
{
    ListNode L1 = SetupList();
    ListNode L2 = SetupList();//构建两个线性表 元素个数至少一个 
    Sort_Descend(L1);
    Sort_Descend(L2);//降序排序
    printf("链表L1:");
    DisplayList(L1);
    printf("\n链表L2:");
    DisplayList(L2);
    /*开始合并 
    思路1 插入排序,题目是原来是递减的,现在要求合并后递增,同时利用原节点,改代码利用的是节点L1.
    思路2 直接把L2插入L1尾部  调用Sort_Ascend函数  太简单就不写了 
    */ 

    ListNode listnode = L1;
    L1 = L1->next->next; //L1从第二个节点开始 
    listnode->next->next = NULL;//断开L1 
    L2 = L2->next;//L2从第一个节点开始
    ListNode pre;//每次判断的前一个结点
    ListNode cur;//需要比较的当前节点 
    while(L1 != NULL || L2 != NULL)
    {
        
        ListNode tmp;
        if(L1 != NULL && L2 != NULL)//找出两个节点中值小的那一个,如果一个为空,则直接取另一个 
        {
            if(L1->val < L2->val)
            {
                tmp = L1;
                L1 = L1->next;    
            }    
            else{
                tmp = L1;
                L1 = L1->next;    
            }
        } 
        else if(L1 == NULL){
            tmp = L2;
            L2 = L2->next;
        }
        else{
            tmp = L1;
            L1 = L1->next;
        }
        pre = listnode;//每次判断的前一个结点
        cur = listnode->next;// 需要比较的当前节点 
        while(cur != NULL)
        {
            if(cur->val > tmp->val)//小于当前节点的值则需要插入 
            {
                tmp->next = cur;
                pre->next = tmp;
                break;    
            }    
            else if(cur->val == tmp->val)//相等则去重 
            {
                break;
            } 
            else if(cur->next == NULL)//到达链表尾部,插入尾部 
            {
                cur->next = tmp;
                tmp->next = NULL;
                break;
            }
            else
            {
                cur = cur->next;
                pre = pre->next;
            }
        }

    } 
    L1 = listnode; 
    printf("\n合并后的链表:");
    DisplayList(L1);     

void Student_Sort()// 17年829和922真题 使及格的成绩在不及格成绩的前面 要求O(n)时间复杂度 
{
    vector<int > student;
    int n;
    printf("请输入学生个数n:");
    scanf("%d",&n);
    printf("请输入所有学生成绩:");
    for(int i = 0;i < n;i++)
    {
        int score;
        scanf("%d",&score);
        student.push_back(score);
    }
    //利用快排的思想 前后同时向中间扫描 然后交换 
    int begin = 0;
    int end =  n-1;
    while(begin < end)
    {
        while(begin < n && student[begin] >= 60 )
            begin++;
        while(end >= 0 && student[end] < 60)
            end--;
        if(begin > end)
            break;
        int tmp = student[begin];
        student[begin] = student[end];
        student[end] = tmp;    
        begin++;
        end--;    
    }
    for(int i = 0;i < n;i++)
        printf("%d ",student[i]); 
    
}

void Delete_Duplicate()//2016年 829和922真题 删除重复节点
{
    ListNode head = SetupList();
    ListNode listnode = head->next;
    while(listnode != NULL)
    {
        ListDelete(listnode,listnode->val);//调用删除函数 
        listnode = listnode->next;
    }
    DisplayList(head);

void SimpleSort()//15年829和922真题 简单选择排序
{
    ListNode head = SetupList();
    ListNode listnode = head->next;
    while(listnode != NULL)
    {
        ListNode min = listnode; //假设当前值是最小值 
        ListNode  cur = listnode->next;
        while(cur != NULL)
        {
            if(min->val > cur->val)
                min = cur;
            cur = cur->next;
        }//找到最小值的节点 
        int tmp = listnode->val;
        listnode->val = min->val;
        min->val = tmp;//交换节点的值 
        listnode = listnode->next;    
    } 
    DisplayList(head);

void AdjustList()//14年829和922真题 偶数次序的节点倒序插入后边 
{
    int flag = 1;//奇偶节点的标志 
    ListNode head = SetupList();
    ListNode pre = head;//当前节点的前驱 
    ListNode cur = head->next;//当前节点 
    ListNode end = head; //最后一个节点an 
    ListNode post = NULL;// end节点的后继
    while(end->next != NULL) { end = end->next; } //找到最后一个节点
    while(cur != end)
    {
        if(flag == 2)//偶数节点
        {
            ListNode tmp = cur;
            pre->next = cur->next;
            cur = cur->next;//去掉偶数节点 
            end->next = tmp;
            tmp->next = post;
            post = tmp;//插入an节点的后面 
            flag = 1;    //下一个是奇数节点 
        } 
        else
        {
            flag = 2; //下一个是偶数节点
            cur = cur->next; 
            pre = pre->next; 
        }
    }
    DisplayList(head);     
}
 
void IntersectionList()//13年829和922真题 求AB链表的交集 并排序
{
    ListNode A = SetupList();
    ListNode B = SetupList();    
    Sort_Ascend(A);
    Sort_Ascend(B); //A B递增有序 
    printf("A链表:");
    DisplayList(A);
    printf("\nB链表:");
    DisplayList(B);
    /*
        开始求交集 注意:A里面可能有重复的元素,还需要去重
        思路1 利用Delete_Duplicate函数,先对A去重,然后利用ListFind函数
        判断A里面的元素是否在B表,不在则删除,最后对A表调用Sort_Descend函数排序
        因为考试题只有一个,所以我们采用思路2
        思路2 通过ListFind函数分别查找A B表,找出交集元素,以及删除A中重复元素 ,
        中间采用插入排序的思想使A表倒序 
    */ 
    ListNode pre = A;
    ListNode cur = A->next;
    while(cur != NULL)
    {
        if(ListFind(B,cur->val) && !ListFind(cur,cur->val) ){ pre = pre->next; cur = cur->next; }    //B中有该节点 A中没重复的 
        else if(ListFind(B,cur->val) && ListFind(cur,cur->val) )//B中有 A中也有 删除该节点 
        { 
            ListNode tmp = cur;
            pre->next = cur->next;
            cur = cur->next;
            free(tmp);
        }
        else//B中没有 
        {
            ListNode tmp = cur;
            pre->next = cur->next;
            cur = cur->next;
            free(tmp);
        }
    } 
    Sort_Descend(A);
    printf("\nAB链表的交集降序排列:");
    DisplayList(A);

int OperateList()//2018年829和922真题 调整链表使负数节点在正数节点后面且返回第一个负数节点位置
{
    /*
        思想: 找到负数节点 插入到尾节点 ,同时第一次就找到了第一个负数节点
        或者最后一个正数节点的位置,如果前面有一个节点插入到尾部,则位置减一 
    */
    ListNode head = SetupList();//建立链表
    int index = 1;
    ListNode end = head->next; //尾节点 用于插入 
    ListNode post = NULL; //尾节点的后继 
    ListNode pre = head; //当前节点的前驱 
    ListNode cur = head->next; //当前节点
    while(end->next != NULL) //找到尾节点 同时找到节点位置 
    {
        end = end->next;
        index++;    
    } 
    while(cur != end) //当前节点未到达尾节点 
    {
        if(cur->val < 0)
        {
            ListNode tmp = cur;
            pre->next = cur->next;
            cur = cur->next; // 断开负节点 
            tmp->next = post;
            end->next = tmp;
            post = end->next; //插入尾节点 
            index--; //位置要减少一  因为少了一个节点 
        } 
        else
        {
            cur = cur->next;
            pre = pre->next;
        }
    }
    if(end->val >= 0) //最好特别判断一下尾节点 如果值大于零 说明位置要加一
        index++; 
    //DisplayList(head);    输出结果 没问题 
    return index;

void  Sort_Negative() //2012年922真题 O(n)时间内使负数在正数前面
{
    /*
        算法思想:思路和18年思路基本一致
    */    
    ListNode head = SetupList();//建立链表
    ListNode end = head->next; //尾节点 用于插入 
    ListNode post = NULL; //尾节点的后继 
    ListNode pre = head; //当前节点的前驱 
    ListNode cur = head->next; //当前节点
    while(end->next != NULL) //找到尾节点 同时找到节点位置 
    {
        end = end->next;    
    } 
    while(cur != end) //当前节点未到达尾节点 
    {
        if(cur->val > 0)
        {
            ListNode tmp = cur;
            pre->next = cur->next;
            cur = cur->next; // 断开负节点 
            tmp->next = post;
            end->next = tmp;
            post = end->next; //插入尾节点 
        } 
        else
        {
            cur = cur->next;
            pre = pre->next;
        }
    }
    DisplayList(head);

int main()
{
    ListNode listnode;
    //listnode = SetupList();
    //DestroyList(listnode);
    //ClearList(listnode);
    //cout<<listnode->val;
    //ListLength(listnode);
    //Sort(listnode);
    //DisplayList(listnode);
    //MergeSort();
    //Student_Sort();
    //Delete_Duplicate();
    //SimpleSort();
    //AdjustList();
    //IntersectionList();
    //printf("%d",OperateList() );
    //Sort_Negative();
    return 0;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值