zoukankan      html  css  js  c++  java
  • 数据结构--线性表(单链表)

    正在学习数据结构,第一步是线性表,写一个bookLinkList.

    同时开始用vianal studio. 当然不是很熟悉这个IDE,但感觉挺厉害的。

    下面的这个booklist 不是本人写的,感谢Liu老师。

     

    链表是一种动态结构,整个可用存储空间可为多个链表共同享用。

    每个链表占用的空间不需要预先分配划定,而是系统按需及时生成。

    建立线性表的链式存储结构的过程是一个动态生成链表的过程。

    从空表的初始状态起,依次建立各元素节点,并逐个插入链表。


    // BookLinkList.cpp : This file contains the 'main' function. Program execution begins and ends there.
    // by lyj.
    
    
    #include <iostream>
    using namespace std;
    #define OK 1
    #define ERROR 0
    #define OVERFLOW -2
    typedef int Status;
    
    typedef struct Book
    {
        char no[20];
        char name[50];
        float price;
      //符号重载
    bool operator==(const Book& anotherbook) { return (!strcmp(no, anotherbook.no)); } bool operator!=(const Book& anotherbook) { return(strcmp(no, anotherbook.no)); } friend istream &operator >> (istream &i, Book& b)//输入流 { cout << "请输入书号:"; i >> b.no; cout << "请输入书名:"; i >> b.name; cout << "请输入价格:"; i >> b.price; cout << " "; return i; } }Book; typedef struct LNode//(1)LNode是结构类型名 { Book data; struct LNode *next;//(2)第二个LNode是用的(1)定义了一个LNode类型的指针 }LNode, *LinkList;//(3)第三个LNode是(1)结构体的别名,这里用了相同的名字。LinkList=LNode *; //一般用LinkList定义单链表头指针,用LNode*定义某个节点指针

    *** 注意区分头结点,首元结点,头指针。

        初始化链表(只有一个头节点的空链表)

    Status InitList(LinkList &L)
    {
        L = new LNode;
        L->next = NULL;
        return OK;
    }

    ——下面的函数是假定链表已经存在多个节点:


    1、取值   用指针p指向首元结点,用 j 做计数器初值赋1 。从首元结点开始依次顺着链域next向下访问,只要指向当前节点的指针p不为NULL,并没有达到序号为 i 的节点,则循环操作:p指向下一个节点,计时器 j 相应加1 。取值算法的时间复杂度为:O(n)

    tatus GetElem(LinkList L, int i, Book &e)
    {
        LNode *p; int j;
        p = L->next; j = 1;
        while (p && j < i)
        {
            p = p->next;
            j++;
        }
        if (!p || j > i) return ERROR;
        e = p->data;
        return OK;
    }

     2、查找 从链表的首元结点出发,依次将节点值和给定值e进行比较,返回查找结果。查找算法时间复杂度也为:O(n)

    LNode *LocateElem(LinkList L, Book e)
    {
        LNode *p;
        p = L->next;
        while (p && p->data != e)
            p = p->next;
        return p;
    }

     3、插入 (可插入位置为n+1个)时间复杂度也为:O(n)

    Status ListInsert(LinkList &L, int i, Book e)
    {
        LNode *s, *p; int j;
        p = L; j = 0;
        while (p && j < i - 1) { p = p->next; j++; }//查找第i-1个节点,p指向该节点
        if (!p || j > i - 1) return ERROR;
        s = new LNode;
        s->data = e;//将e存入*s的数据域
        s->next = p->next;//把p的下一个节点的地址给*s的指针域,即将p后面的节点连入s的尾部
        p->next = s;//将s本身的地址(理解为s的头)放入p的尾部
        return OK;
    }

     删除节点(按序号删除 和 按节点中数据项关键字删除)

    Status ListDelete(LinkList &L, int i)   //按序号删除元素(结点)
    {
        LNode *p, *q; int j;
        p = L; j = 0;
        while (p->next && j < i - 1) { p = p->next; j++; }
        if (!p->next || j > i - 1) return ERROR;
        q = p->next;
        p->next = q->next;
        delete q;
        return OK;
    }
    Status DelElem(LinkList &L, Book e)  //按结点中数据项的关键字值删除结点
    {
        LNode *p, *q;
        p = L;
        while (p->next && strcmp(p->next->data.no, e.no))
        {
            p = p->next;
        }
        if (!p->next) return ERROR;
        q = p->next;
        p->next = q->next;
        delete q;
        return OK;
    }

    4、链表销毁

    Status DestroyList(LinkList &L)
    {
        LNode *p;
        while (L->next != NULL)
        {
            p = L;
            L = L->next;
            delete p;
        }
        delete L;
        return OK;
    }

    5、链表显示

    void ListDisplay(LinkList L)
    {
        cout << "书号	书名	价格
    ";
        while (L->next != NULL)
        {
            L = L->next;
            cout << L->data.no << "	" << L->data.name << "	" << L->data.price << "
    ";
        }
    }

    前面只创建了有一个头结点的空链表,下面将建立一个包含若干个节点的链表

    根据节点插入位置不同,链表的创建可以分为:前插 和 后插

    void CreateList_H(LinkList &L, int n)  //前插法
    {
        LNode *p;
        L = new LNode;
        L->next = NULL;
        for (int i = 0; i < n; i++)
        {
            p = new LNode;
            cin >> p->data;
            p->next = L->next;
            L->next = p;
        }
    }
    void CreateList_R(LinkList &L, int n)  //后插法
    {
        LNode *r, *p;
        L = new LNode;
        L->next = NULL;
        r = L;
        for (int i = 0; i < n; i++)
        {
            p = new LNode;
            cin >> p->data;
            p->next = NULL;
            r->next = p;
            r = p;
        }
    }

    差不多就是这样,然后来一个main测试一下

    int main()
    {
        LinkList bookLinkList;
        char ch; int n;
        cout << "
    +-------------------------------------------------------+
    ";
        cout << "+ 请选择要进行的操作:					+
    ";
        cout << "+	<按数字键1> 创建一个只含头结点的空的单链表	+
    ";
        cout << "+	<按数字键2> 创建一个包含头结点和n个元素的单链表	+
    ";
        cout << "+	<按其他任意键> 退出程序				+
    ";
        cout << "+-------------------------------------------------------+
    ";
        ch = _getwch();
        if (ch == '1')
        {
            InitList(bookLinkList);
        }
        else if (ch == '2')
        {
            cout << "
    请输入单链表中要包含的元素个数:";
            cin >> n;
            cout << "请选择:<a>使用前插法	<b>使用后插法
    ";
            while (1)
            {
                ch = _getwch();
                if (ch == 'a')
                {
                    CreateList_H(bookLinkList, n);
                    break;
                }
                else if (ch == 'b')
                {
                    CreateList_R(bookLinkList, n);
                    break;
                }
            }
        }
        else
        {
            exit(0);
        }
        while (1)
        {
            cout << "
    
    ------------------------------------------------------------------------------------
    ";
            cout << "+请选择要进行的操作:<a>显示    <b>插入元素    <c>删除元素    <d>查找    <x>退出+
    ";
            cout << "------------------------------------------------------------------------------------
    ";
            ch = _getwch();
            if (ch == 'x')
                break;
            else if (ch == 'a')
                ListDisplay(bookLinkList);
            else if (ch == 'b')
            {
                int i;
                cout << "请输入插入的位置:";
                cin >> i;
                Book b;
                cin >> b;
                if (ListInsert(bookLinkList, i, b) == OK)
                    cout << "元素插入第" << i << "个位置成功。
    ";
                else
                    cout << "元素插入第" << i << "个位置失败。
    ";
            }
            else if (ch == 'c')
            {
                cout << "请选择:<a>按位置序号删除元素	<b>按元素中数据项的关键字值删除元素
    ";
                while (1)
                {
                    ch = _getwch();
                    if (ch == 'a')
                    {
                        cout << "请输入要删除的元素的位置序号:";
                        int i;
                        cin >> i;
                        if (ListDelete(bookLinkList, i) == OK)
                            cout << "删除成功!
    ";
                        else
                            cout << "删除失败!
    ";
                        break;
                    }
                    else if (ch == 'b')
                    {
                        cout << "请输入要删除的书籍的书号:";
                        Book b;
                        cin >> b.no;
                        if (DelElem(bookLinkList, b) == OK)
                            cout << "删除成功!
    ";
                        else
                            cout << "删除失败!
    ";
                        break;
                    }
                }
            }
            else if (ch == 'd')
            {
                cout << "请输入要查找的书籍的书号:";
                Book t;
                cin >> t.no;
                LNode *p = LocateElem(bookLinkList, t);
                if (p == NULL)
                    cout << "查找失败!
    ";
                else
                {
                    cout << "查找成功! 找到的书籍为:
    ";
                    cout << "书号	书名	价格
    ";
                    cout << p->data.no << "	" << p->data.name << "	" << p->data.price << "
    ";
                }
            }
    
        }
    
        DestroyList(bookLinkList);
    }
  • 相关阅读:
    XCode
    容器中的诊断与分析4——live diagnosis——LTTng
    容器中的诊断与分析3——live diagnosis——lldb
    容器中的诊断与分析2——live diagnosis——perf
    容器中的诊断与分析1——简介
    HTTP之gRPC
    Markdown介绍
    目标指定法——S.M.A.R.T.
    Facebook token更新
    代理配置
  • 原文地址:https://www.cnblogs.com/cjwen/p/10501570.html
Copyright © 2011-2022 走看看