数组和链表对比有什么优势和缺点?
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;
}
}
}