单链表的整表创建
算法思路:
-声明一结点p和计数器变量i;
-初始化一空链表L
-让L的头结点的指针指向NULL,即创建一个带头结点的单链表;
-循环实现后继结点的赋值和插入。
头插法建立单链表
头插法从一个空表开始,生成新节点,读取数据存放到新节点的数据域中,然后将新节点插入到当前链表的表头上,直到结束为止。
简单来说,就是把新加进的元素放在表头后的第一个位置:
-先让新节点的next指向头结点之后
-然后让表头的next指向新结点
/*头插法简历单链表示例*/
/*头插法简历单链表示例*/
void CreateListHead(LinkList &L,int n){
LNode *p;
int i;
L = new LNode;
L->next = NULL;
L->data = n;
for(i=0;i<n;i++){
p = new LNode; //生成新结点
p->data = i;
p->next = L->next;
L->next = p;
}
}
链表的遍历
head不断往后移动
void DisplayList(LinkList &head){
head = head->next;
while(head != NULL){
cout<<head->data<<" ";
head = head->next;
}
cout<<endl;
}
尾插法建立单链表
void CreateListTail(LinkList &L,int n){
LNode *p,*r;
int i;
srand(time(0)); //初始化随机数种子
L = new Node;
r = L;
for(i=0;i<n;i++){
p = new Node; //生成新结点
p->data = rand()%100+1;
r->next = p; //用r来接纳新节点
r = p; //r指向新的尾结点p
}
r->next = NULL; //元素已经全部装入链表L中
//L的终端节点指针域为NULL,L建立完成
}
对于这两句的理解
r->next = p;
r = p;
以此类推,得到
很多人可能会对这一行代码产生疑问
假设没有这一句,就会让L对链表进行直接操作,当完成尾插后,L的位置会在链表的末尾,指向NULL,这就会使当我们对链表进行遍历时,不会输出任何内容!
所以我们需要借助一个临时的指针来代表L执行创建操作,这样L就会一直指向头结点,当我们遍历的时候,可以正常输出了。
单链表的整表删除
算法思路:
-声明结点p和q;
-将第一个结点赋值给p,下一个节点赋值给q
-循环执行释放p和将q赋值给p的操作
Status ClearList(LinkList &L){
LNode *p,*q;
p = L->next;
while(P){
q = p->next;
delete p;
p = q;
}
L->next = NULL;
return OK;
}
单链表结构和顺序存储结构优缺点
存储分配方式:
-顺序存储结构用一段连续的存储单元一词存储线性表的数据元素。
-单链表采用链式存储结构,用一组任意的存储单元存放线性表的元素。
时间性能:
查找:
—顺序存储结构O(1)
—单链表O(n)
插入和删除:
—顺序存储结构需要平均移动表长一半的元素,时间为O(n)
—单链表在计算出某位置的指针后,插入和删除时间仅为O(1)
空间性能:
—顺序存储结构需要预分配存储空间,分大了,容易造成空间浪费,分小了,容易发生溢出。
—单链表不需要分配存储空间,只要有就可以分配,元素个数也不受限制。
综上所述,
—若线性表需要频繁查找,很少进行插入和删除操作时,宜选用顺序存储结构。
—若需要频繁插入和删除时,宜选用单链表结构。
参考视频:1.小甲鱼
2.https://www.bilibili.com/video/BV1tE41117id?from=search&seid=6006657257565479507
3.https://www.bilibili.com/video/BV1VE411B7LG?from=search&seid=8136219197100216049