学习数据结构——线性表与链表

来源:互联网 发布:淘宝魔切页面 编辑:程序博客网 时间:2024/06/05 13:28

线性表是一种最基本的数据结构,通常可以分为顺序表和链表。
顺序表即数据的存储空间是连续的,而链表的前后元素需要靠指针来连接。
顺序表简单,但是通常存在着

  • 插入删除操作时需要移动大量数据,效率极低;
  • 最大表长度难以估计,太大了浪费空间,太小了容易溢出。

但是链表的性质却可以很好的解决以上两个问题。以下是两个链表的示例程序。一个静态,一个动态,均有较详细的注释,以备日后回顾复习。

注意,在Visual Studio的高版本(一般高于VS2013)中运行两个程序时,`scanf()`函数会报错,或者出现这样的问题:error C4703: 使用了可能未初始化的本地指针变量“xxx”这时可以打开 项目属性->配置属性->C/C++->SDL检查,选择SDL检查为“否”,即可解决问题。

静态链表示例程序

用数组模拟静态的链表,长度预先定义好,不能动态分配内存。

//简单静态链表#include <iostream>using namespace std;struct student{    long num;    float score;    struct student * next;  //指向该类结构体};  //注意分号int main(){    struct student a,b,c,* head,* p;    a.num = 0001;    a.score = 99;    b.num = 0002;    b.score = 98;    c.num = 0003;    c.score = 97;    head = &a;     //头指针     a.next = &b;    b.next = &c;    c.next = NULL;  //尾指针     p = head;   //迭代的时候不能用头指针本身去迭代,否则就乱了     do    {        cout << p->num << " " << p->score << endl;        p = p->next;    }while( p != NULL );    getchar();   //输出结果后起到暂停作用 }

动态链表示例程序,包含链表常用的若干种操作

用指针实现动态链表,malloc函数和free函数可以实现内存的动态分配。具有较大灵活性。

注意在C++语言中使用printf()函数要引入标准输入输出库。C语言中使用#include <stdio.h>,而C++语言中使用#include <cstdio>来实现。

//动态链表程序#include "stdafx.h"#include <cstdio>#include <iostream>#include <cstdlib>using namespace std;using namespace std;typedef int ElemType;typedef struct List * link;typedef struct List Lnode;struct List    //定义链表{    ElemType data;    struct List * next;};link setnull(link Head)   //置空链表,输入一个链表的头指针{    link p;    p = Head;    //头指针赋给指针p    while (p != NULL)    {        p = p->next;    //p指向链表的下一个元素        free(Head);    //把p指针的上一个指针(Head)所占空间释放        Head = p;    //p所指的结点(node)成为新的Head    }    return Head;}link insert(link Head, ElemType x, int i)  // Head是已知链表,x是要插入的数,i是插入位置{    link NewPoint, p = Head;    int j = 1;    NewPoint = (link)malloc(sizeof(Lnode));  //生成一个link类型的,长度为一个节点的内存空间    NewPoint->data = x;    if (i == 1)  //如果插入位置是第一个,直接令NewPoint为头指针,NewPoint的next指向原第一个结点    {        NewPoint->next = Head;        Head = NewPoint;    }    else    {        while (j<i - 1 && p->next != NULL) //把p指针从头移到要插入的前一位        {            p = p->next;            j++;  //此时j应该等于i-1        }        if (j == i - 1)  //把NewPoint插进去        {            NewPoint->next = p->next;            p->next = NewPoint;        }        else  //超过范围就报错        {            printf("insert is failure,i is not right!");        }    }    return Head;  //最后返回更改后的链表指针}link create(link Head) //生成链表{    ElemType newData;  //新数据    link NewPoint;  //新指针    Head = (link)malloc(sizeof(Lnode));  //给头指针分配一个节点大小的内存空间    printf("please input number: \n");    printf("caution! 倒序输入 \n");    scanf("%d", &newData);    printf("you type %d as the last number\n", newData);    //cin >> newData;    Head->data = newData;    Head->next = NULL;  //头指针的后面暂无结点    while (1)    {        NewPoint = (link)malloc(sizeof(Lnode));  //产生新节点        if (NewPoint == NULL)  //如果分配内存失败,跳出while        {            break;        }        printf("please input number : input '-1' means exit\n");        scanf("%d", &newData);        //cin >> newData;        if (newData == -1) //结束标志        {            return Head;        }        NewPoint->data = newData;  //把NewPoint接在Head前面        NewPoint->next = Head;        Head = NewPoint;    }    return Head;}int length(link Head)  // 计算一个链表的长度{    int len = 0;    link p;   //不要直接操作Head,会改乱指针    p = Head;    while (p != NULL)  //只要p不是空指针,就计数    {        len++;        p = p->next;    }    return len;}ElemType get(link Head, int i)  // 返回Head链表的i位置的数据{    int j = 1;    link p;    p = Head;    while (j<i && p != NULL)    {        p = p->next;        j++;    }    if (p != NULL)    {        return (p->data);    }    else//这种情况出现在给定的i超过了链表的长度    {        //printf("data is error!");        cout << "data is error!";    }    return -1;}int locate(link Head, ElemType x)  //在给定链表中确定数据x的位置{    int n = 0;    link p;    p = Head;    while (p != NULL && p->data != x)  //一直找,找到x前一个停下    {        p = p->next;        n++;    }    if (p == NULL) //如果Head链表里没有这个数据,p会最终指到NULL上    {        return -1;    }    else    {        return n + 1;    }}void display(link Head)  //在屏幕上打印链表{    link p;    p = Head;    if (p == NULL)    {        //printf("\nList is empty");        cout << "\nList is empty";    }    else    {        do        {            printf("%d", p->data);            p = p->next;        } while (p != NULL);    }    cout << endl;}link connect(link Head1, link Head2)  //将两个链表连接起来,Head1在前,Head2在后{    link p;    p = Head1;    while (p->next != NULL)  //p指针一直指到Head1链表的最后一个结点处    {        p = p->next;    }    p->next = Head2;  //在Head1最后接上Head2链表的第一个结点    return Head1;}link del(link Head, int i)  //删除{    int j = 1;    link p, t;    p = Head;    if (i == 1)    {        p = p->next;  //如果要删除的是第一个位置的数据,就把p指针指向下一个元素,然后将Head释放        free(Head);  //释放p所指的空间        Head = p;  //新的头指针    }    else  //如果要删除的元素不在第一个位置    {        while (j < i - 1 && p->next != NULL)  //先将p指向要删除的结点的前一个位置,而且要保证要删除的元素没有超出链表的长度        {            p = p->next;            j++;        }        if (p->next != NULL && j == i - 1)        {            t = p->next;            p->next = t->next;  //直接跳过第i个结点,将第i-1个结点和第i+1个结点连在一起        }        if (t != NULL)        {            free(t);  //把中间变量释放掉        }    }    return Head;}int compare(link Head1, link Head2)  //比较两个链表是否相同:长度一致,且数据相同{    link p1, p2;    p1 = Head1;    p2 = Head2;    while (1)    {        if ((p1->next == NULL) && (p2->next == NULL))  //当Head1和Head2同时达到链尾才成立        {            return 1;  //两链表相同        }        if (p1->data != p2->data)  //比较过程中只要有不一样的数据就返回0        {            return 0;        }        else        {            p1 = p1->next;  //不断迭代            p2 = p2->next;        }    }}int main(){    int l;    link head1 = NULL;    link head2 = NULL;    printf("\nNow we generate the first linked list\n");    head1 = create(head1);  //生成第一个链表    printf("\nHead1 is :\n");  //显示出来    display(head1);    printf("\nNow we generate the second linked list\n");    head2 = create(head2);  //生成第二个链表    printf("\nHead2 is :\n");  //显示出来    display(head2);    printf("\nNow we compare the two linked lists\n");  //比较两个链表是否相同    l = compare(head1, head2);    printf("\nl is %d\n", l);    printf("\nNow we connect two linked lists\n");    connect(head1, head2);  //将head1与head2接起来    printf("\nHead1 + Head2 is \n");    display(head1);    printf("\nNow we calculate the first linked list\n");    l = length(head1);  //计算head1的长度    printf("\nthe length of link1 is %d\n", l);    l = get(head1, 3);  //获取head1链表第三个元素的值    printf("\nthe 3th element of link1 is %d\n", l);    l = locate(head1, 12);  //查找12在链表中的位置,没有则返回1    printf("\nlocate 12 is %d \n", l);    printf("\nNow we insert 555 to 8th of the first linked list\n");    head1 = insert(head1, 555, 8);  //在第8位插入数据555    display(head1);    printf("\nNow we delete the 7th element of the first linked list\n");    head1 = del(head1, 7);  //删除第7个结点    display(head1);    printf("\nNow we clear the first linked list\n");    head1 = setnull(head1);  //将head1置空    display(head1);    printf("\nNow wait to exit: press any key and enter\n");    cin >> l;    return 0;}
原创粉丝点击