单链表的基本操作【超全】

实验二  链表的基本操作

一、实验目的

1、掌握链表的建立、插入元素、删除表中某元素的算法。

2、对线链表相应算法的时间复杂度进行分析。

二、实验要求

1.实验前做好充分准备,包括复习第二章所学内容,事先预习好本次实验内容。

2.实验时记录实验结果,按要求完成各题。

3.实验结束后,给出实验总结与分析并及时给出本次实验的实验报告。

三、实验内容

1.完成并实现如下链表的基本操作要求:编写测试函数运行程序,给出结果每个基本操作的运行截图。

#include

#include

#include

typedef int ElemType;  //定义类型

typedef struct LNode  //定义结点

{

    ElemType data;   //数据域

    struct LNode *next;  //指向后继结点的指针域

}LNode,*PNode;  //PNode为节点类型指针

typedef struct LinkList  //定义链表

{

    PNode first;  //头指针

    PNode last;  //尾指针

    int list_size;  //链表中有效元素个数

}LinkList;

要求:完成并实现如下单链表的基本操作

/基本操作/

void InitLinkList(LinkList *list);//初始化链表

理解代码

LNode *_buyNode(ElemType Item);//新增结点

理解代码

void push_front(LinkList *list,ElemType x);//向链表中头插结点(5分)

代码:

LinkList* push_front(LinkList* list, ElemType x)

{  if (list == NULL) {

    printf("头插传入参数有误");

        return list;

}

    LinkList* s = (LinkList*)malloc(sizeof(list));

      s->data=x;

    s->next = list->next;

    list->next = s;

return list;

}

截图:

void push_back(LinkList *list,ElemType x);//向链表中尾插结点(5分)

代码://尾插

LinkList* push_back(LinkList* list, ElemType x)

{

    if (list == NULL) {

        printf("尾插传入参数有误");

        return list;

    }

    LinkList* r ;

    r = list;

    while (r->next!=NULL) {//让尾指针指向尾部

        r = r->next;

    }

    LinkList* s = (LinkList*)malloc(sizeof(list));

    s->data = x;

    s->next = NULL;

    r->next = s;//尾结点r

    r = s;//r指向新的尾结点

    return list;

}

截图:

正在上传…重新上传取消

void showList(LinkList *list);//显示链表元素(10分)

代码:

void showList(LinkList* list) {

    LinkList* temp = list;//将temp指针重新指向头结点

    //只要temp指针指向的结点的next不是Null,就执行输出语句。

    while (temp->next) {

        temp = temp->next;

        printf("%d ", temp->data);

    }

    printf("\n");

}截图:

正在上传…重新上传取消

void pop_back(LinkList *list);//尾部删除结点(10分)

代码:

LinkList* pop_back(LinkList* list)

{

    if (list == NULL) {

        printf("尾删传入参数有误");

        return list;

    }

    LinkList* r= list;//尾结点

    LinkList* q=NULL;//指向尾结点前一结点

    while (r->next != NULL) {//让尾指针指向尾部

        q = r;

        r = r->next;

    }

    q->next = NULL;

    return list;

}

截图:

正在上传…重新上传取消

void pop_front(LinkList *list);//头部删除节点(10分)

代码:

//头删

LinkList* pop_front(LinkList* list)

{

    if (list == NULL) {

        printf("删传入参数有误");

        return list;

    }

    LinkList* r = NULL;//被删除结点指针

    LinkList* q = list;

    r = q->next;

    q->next = r->next;

    free(r);

    return list;

}

截图:

正在上传…重新上传取消

int length_list(LinkList *list);//返回链表长度(10分)

代码:

int length_list(LinkList* list){

    if (list == NULL) {

        printf("长度传入参数有误");

        return 0;

    }

    LinkList* p=list->next;//指向第一个结点

    int i = 0;

    while (p) {

        i++;

        p = p->next;

    }

    return i;

}

截图:

正在上传…重新上传取消

void insertLinklist_pos(LinkList *list,int pos,ElemType key);//按照pos指定的位置插入元素(10分)

代码:

LinkList* insertLinklist_pos(LinkList* list, int pos, ElemType key) {

    LinkList* temp = list;//创建临时结点temp

    LinkList* c = NULL;

    int i = 0;

    //首先找到要插入位置的上一个结点

    for (i = 1; i < pos; i++) {

        if (temp == NULL) {

            printf("插入位置无效\n");

            return list;

        }

        temp = temp->next;

    }

    //创建插入结点c

    c = (LinkList*)malloc(sizeof(LinkList));

    c->data = key;

    //向链表中插入结点

    c->next = temp->next;

    temp->next = c;

    return list;

}

截图:

正在上传…重新上传取消

void delete_LinkList_val(LinkList *list,ElemType x);//删除第一个值为x的元素(10分)

代码:

LinkList* delete_LinkList_val(LinkList* list, int x) {

    LinkList* temp = list;

    LinkList* del = NULL;

    int i = 0;

    //遍历到被删除结点的上一个结点

    while (temp) {

        if (temp->data == x)//temp当前指向的就是要删除的那个结点

            break;

        del = temp;//要删除的前一结点

        temp = temp->next;

    }

    del->next = temp->next;//跳过值为x的结点

    free(temp);//手动释放该结点,防止内存泄漏

    return list;

}

截图:

正在上传…重新上传取消

void sortLinkList(LinkList *list); //排序

理解代码

void reverseLinkList(LinkList *list);//逆置链表元素

理解代码

LinkList* reverseLinkList(LinkList* list) {

    list = list->next;

    LinkList* temp; // 保存cur的下一个节点

    LinkList* cur = list;

    LinkList* pre = NULL;

    while (cur) {

        temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next

        cur->next = pre; // 翻转操作

        // 更新pre 和 cur指针

        pre = cur;

        cur = temp;

    }

   

    return pre;

}
运行:

正在上传…重新上传取消

int findval_val(LinkList *list,ElemType key);//查找链表中首个值为key的元素位置(10分)

代码:

int findval_val(LinkList* list, ElemType key) {

    LinkList* p = list;

    p = list->next;

    int j = 1;

    while (p && p->data != key) {

        p = p->next;

        j++;

    }

    if (p) return j;

    else return 0;

}

截图:

正在上传…重新上传取消

int countX(LinkList *list,ElemType x) 统计大于某个值的节点个数(10分)

代码:

int countX(LinkList* list, ElemType x) {

    LinkList* p = list;

    p = list->next;

    int count = 0;

    while (p ) {

        if (p->data>x) {

            count++;

        }

        p = p->next;   

    }

    return count;

  

}

截图:

正在上传…重新上传取消

void clearLinkList(LinkList *list);//清空单链表

理解代码

void destroyLinkList(LinkList *list);//销毁单链表

理解代码

2.利用单链表结构实现单链表的基本应用

(1)单链表的拆分:拆分单链表l1,使得拆分后的单链表l1存奇数位置元素,l2逆序存偶数位置元素。例如:拆分前l1:1->2->3->4->5->6->7

拆分后:l1:1->3->5->7;

l2:6->4->2   (5分)

代码:

#include 

#include 

typedef int ElemType;

typedef struct Link {

    ElemType data;

    struct Link* next;

}LinkList;

//初始化

LinkList* initLink() {

    LinkList* list = (LinkList*)malloc(sizeof(LinkList));//创建一个头结点

    LinkList* temp = list;//声明一个指针指向头结点,用于遍历链表

    int i = 0;

    //生成链表

    for (i = 1; i < 8; i++) {

        LinkList* a = (LinkList*)malloc(sizeof(LinkList));

        a->data = i;

        a->next = NULL;

        temp->next = a;

        temp = temp->next;

    }

    return list;

}

//正序输出奇数

void jdisplay(LinkList* list) {

    LinkList* temp = list;//将temp指针重新指向头结点

    //只要temp指针指向的结点的next不是Null,就执行输出语句。

    while (temp->next) {

        temp = temp->next;

       if(temp->data%2!=0) printf("%d ", temp->data);

    }

    printf("\n");

}

//逆置链表元素

LinkList* reverseLinkList(LinkList* list) {

    list = list->next;

    LinkList* temp; // 保存cur的下一个节点

    LinkList* cur = list;

    LinkList* pre = NULL;

    while (cur) {

        temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->next

        cur->next = pre; // 翻转操作

        // 更新pre 和 cur指针

        pre = cur;

        cur = temp;

    }

   

    return pre;

}

//倒叙输出偶数

void oredisplay(LinkList* list) {

    LinkList* temp = list;//将temp指针重新指向头结点

    //只要temp指针指向的结点的next不是Null,就执行输出语句。

    while (temp) {

       if(temp->data%2==0)   printf("%d ", temp->data);

           temp = temp->next;

    }

    printf("\n");

}

int mian(){

 LinkList* list = NULL;

    int address;     

    printf("初始化链表为:\n");

    list = initLink();

display(list);

 printf("拆分后链表:\n");

    jdisplay(list);

    LinkList* pre = reverseLinkList(list);

    oredisplay(pre);}

截图:

正在上传…重新上传取消

(2)链表的合并:将有序单链表l1、l2合并为l3后仍有序。(5分)

代码:#include 

#include 

typedef int ElemType;

typedef struct Link {

    ElemType data;

    struct Link* next;

}LinkList;

LinkList* initLink() {

    LinkList* list = (LinkList*)malloc(sizeof(LinkList));//创建一个头结点

    LinkList* temp = list;//声明一个指针指向头结点,用于遍历链表

    int i = 0;

    //生成链表

    for (i = 1; i < 8; i++) {

        LinkList* a = (LinkList*)malloc(sizeof(LinkList));

        a->data = i;

        a->next = NULL;

        temp->next = a;

        temp = temp->next;

    }

    return list;

}

void display(LinkList* list) {

    LinkList* temp = list;//将temp指针重新指向头结点

    //只要temp指针指向的结点的next不是Null,就执行输出语句。

    while (temp->next) {

        temp = temp->next;

        printf("%d ", temp->data);

    }

    printf("\n");

}

//合并

void MergeList(LinkList* lista, LinkList* listb, LinkList* listc) {

    LinkList* pa = NULL;

    LinkList* pb = NULL;

    LinkList* pc = NULL;

    pa = lista->next;

    pb = listb->next;

    pc = listc = lista;//用La的头节点作为Lc的头节点

    while (pa && pb) {

        if (pa->data <= pb->data) {

            pc->next = pa;

            pc = pa;

            pa = pa->next;

        }

        else {

            pc->next = pb;

            pc = pb;

            pb = pb->next;

        }

    }

    pc->next = pa ? pa : pb;//插入剩余段

    free(listb);

}

int main() {

    LinkList* lista = NULL;

    LinkList* listb = NULL;

    LinkList* listc = NULL;

    printf("初始化链表为:\n");

    lista = initLink();

    printf("lista链表的值:\n");

    display(lista);

    listb = initLink();

    printf("listb链表的值:\n");

    display(listb);

    MergeList(lista, listb, listc);

    printf("listc合并链表的值:\n");

    display(lista);

}

截图:

正在上传…重新上传取消

四、实验小结


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部