zoukankan      html  css  js  c++  java
  • 单链表

    数组和链表对比有什么优势和缺点?

    A 从逻辑结构来看

    A-1. 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况。当数据增加时,可能超出原先定义的元素个数,出现溢出现象;当数据减少时,造成内存浪费。数组中插入、删除数据项时,需要移动其它数据项。
    A-2. 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入、删除数据项。

    B 从内存存储来看

    B-1. (静态)数组从栈中分配空间, 对于程序员方便快速,但是自由度小,随机访问较快
    B-2. 链表从堆中分配空间, 自由度大但是申请管理比较麻烦. 


    #include<iostream> #include<string> using namespace std; typedef struct Node { int data; Node *next; }*pNode; int LengthList(Node * pHead); //创建链表 头结点head不放数据 Node *CreatList() { int iIndex=0; // 用于下面循环 int iLength=0; // 用来存放有效节点的字数 int iValue=0; // 用于临时存放用户输入的数据 Node *pHead = new Node[sizeof(Node)]; // 分配一个不存放有效数据的头结点 Node *pTail = pHead; // 链表的最后一个节点 pTail->next = NULL; // 最后一个节点的指针置为空 cout<<"请输入节点个数:"; cin>>iLength; for(iIndex= 1; iIndex <=iLength; iIndex++) { cout<<""<<iIndex<<"个节点的数值:"; cin>>iValue; pNode pNew = (pNode)malloc(sizeof(Node)); // 为节点分配空间 pNew->data = iValue; //将用户输入的数据赋给节点的成员 pTail->next = pNew; //将最后一个节点的指针指向下一个新的节点 pNew->next = NULL; //将新节点中的指针置为空 pTail = pNew; //将新节点赋给最后的一个节点 } return pHead; } //删除第一个数据为num的节点 Node * DeleNodeElem(Node *head,int num) { Node *pPre=NULL,*pCurr=NULL; pCurr=head->next; pPre=head; while (pCurr->data!=num&&pCurr->next!=NULL) { pPre=pCurr; pCurr=pCurr->next; } if (pCurr->data==num) { pPre->next=pCurr->next; delete pCurr; } else cout<<"Not find the num !"<<endl; return head; } //删除第pos个位置的节点 void DeleNodePos(Node *head, int pos) { int iRetVal=0; int index=1; Node *pCurr=NULL; Node *pPre=NULL; pCurr=head->next; while (index<pos&&pCurr->next!=NULL) { pPre=pCurr; pCurr=pCurr->next; index++; } pPre->next=pCurr->next; iRetVal=pCurr->data; free(pCurr); cout<<"the element you delete is:"<<iRetVal<<endl; } bool Insert_Node(pNode pHead, int pos,int data) { int i =1; pNode p = pHead; while (i < pos && p->next!=NULL ) //通过循环使指针指向要插入哪个节点前的节点。说的自己都不懂了,还是看下面的图吧。 { p = p->next; ++i; } if (p==NULL) { cout<<"ERROR!"<<endl; return false; } pNode pNew = (pNode)malloc(sizeof(Node)); pNew->data = data; pNew->next = p->next; p->next = pNew; return true; } bool IsEmpty(pNode pHead) { if (NULL == pHead->next)//判断头节点的指针部分是否为空 { printf ("链表为空! "); return true; } else { return false; } } //计算链表的长度 int LengthList(Node * pHead) { int length = 0; pNode p = pHead->next; while(NULL != p) { length++; p = p->next; } return length; } //打印链表中的数据 void PrintList(Node *head) { Node *p=NULL; p=head->next; if (p==NULL) { return; } while (p!=NULL) { cout<<"data: "<<p->data<<endl; p=p->next; } } //删除链表 void DeleList(Node *head) { Node *p=NULL,*q=NULL; if (head==NULL) { return; } p=head->next; while (p!=NULL) { q=p; p=p->next; delete q; } head->next=NULL;//这一句要加上 否则会乱指 cout<<"Delete List Success"<<endl; }
    //找出倒数第k个元素  
    void FindElem(Node * pHead, int k)
    {
        Node *pFront=NULL;//
        Node *pBehind=NULL;
        pFront=pHead;
        pBehind=pHead;
        for(int i=0;i<k;i++)
        {
            pFront=pFront->next;
        }
        while(pFront!=NULL)
        {
            pFront=pFront->next;
            pBehind=pBehind->next;
        }
        cout<<"倒数第"<<k<<"个元素是:"<<pBehind->data<<endl;
    
    }
    
    
    //单链表反转
    Node* ReserveList(Node * head)
    {
        cout<<"Begin to Reverse the list:"<<endl;
        Node *pPre=NULL;
        Node *pCurr=head;
        Node *pNex=NULL;
        Node *pRetHead=NULL;
        while (pCurr!=NULL)
        {
            pNex = pCurr->next;
            if (pNex==NULL)
            {
                pRetHead=pCurr;
            }
            pCurr->next=pPre;
            pPre=pCurr;
            pCurr=pNex;
        }
        
        return pRetHead;
    }
    //逆序打印链表
    void PrintListReversly(Node * head)
    {
        if (head->next!=NULL)
        {
            PrintListReversly(head->next);
        }
        cout<<head->data<<endl;
    }
    //找到链表中中间的元素
    void FindMidEle(Node *pHead)
    {
        Node *pOneStep=pHead;
        Node *pTwiStep=pHead;
        if (LengthList(pHead)%2==0)
        {
            cout<<"the length is illegal!"<<endl;
            exit(0);
        }
        
        while(pTwiStep!=NULL)
        {
            pOneStep=pOneStep->next;
            pTwiStep=pTwiStep->next->next;
        }
        cout<<"the middle one is "<<pOneStep->data<<endl;
    }
    
    
    
    
    //链表排序 用的是冒泡排序算法
    void SortList(Node *head)
    {
        if (head==NULL||head->next==NULL)
        {
            return;
        }
        Node *p=head->next;
        int temp=0;
        int len=ListLength(head);
        for (int i=0;i<len-1;i++)
        {
            p=head->next;
            for (int j=1;j<len-i,p!=NULL;j++)
            {
                if (p->data>p->next->data)
                {
                    temp=p->data;
                    p->data=p->next->data;
                    p->next->data=temp;
                }
                p=p->next;
            }
        }
    }
     
  • 相关阅读:
    如何快速打开Github
    vuecli4 如何创建带有vuerouter vuex scss预编译的项目
    ASP.Net Core WebApi几种版本控制对比
    解决Asp.Net Core 3.1 中无法读取HttpContext.Request.Body的问题
    winrar压缩文件但是排除指定目录
    postgresql数据库下导入导出,删除常用命令
    .NetCore使用Swagger+API多版本控制
    ElementUI和Ant Design对比
    自动登录或7天登录的实现
    浏览器脚本按钮功能
  • 原文地址:https://www.cnblogs.com/mu-tou-man/p/3887431.html
Copyright © 2011-2022 走看看