小白学算法1.2——链表
标签:小白学算法
1.什么是链表
链表是一种递归的数据结构,它或者为空,或者指向指向下一个结点。
struct node{ int data; node* next; };
- 看起来很抽象的感觉,就我自己的理解,可以用车链子来模拟链表在计算机中的结构。“链表结点”就是车链子上面的一个个“圆柱结点”,每个“圆柱结点”最多与两个其它“圆柱结点”相连接,如果链条不是环形的,那么头和尾“圆柱结点”只与一个其它的“圆柱结点”相连接
- 结点一般不仅仅包含数据,还包含指向其它结点的指针或者引用
- 链表是有方向的,一般分为单向链表和双向链表。单向链表中的结点就像地下党一样,只能上一个找下一个,不能下一个找上一个;双向链表中的结点就像楼梯一样,可以上可以下,但是不能跨越
- 单向链表一般有一个变量指向链表头,双向链表一般有两个变量指向链表头和尾
- 链表常见的操作有新建,添加,删除和修改
- 链表对于空间的利用率很高,是数组重要的替代方式
2.用单向链表实现一个栈
因为链表是动态申请内存的,所以不需要设置链表的大小。我们只需要设置一个head,用它来进行链表的操作即可,node* head = null;
2.1入栈
void push(int mydata)
{
node* p = (node*)malloc(sizeof(node));//动态申请内存
p->data = mydata;
p->next = NULL;
if (head == NULL)
head = p;
else
{
p->next = head;
head = p;
}
}
malloc
需要包含头文件stdlib.hmalloc
的作用是在内存中申请一段内存空间,返回值为void*
类型,参数表示申请空间的大小,一般配合sizeof()
函数使用sizeof()
参数一般为数据类型,比如结构体node
,int
- 使用
malloc
函数的返回值需要强制转化为具体的类型 - 入栈时如果链表为空,申请一段内存空间,将其作为第一个结点;如果链表不为空,申请一段内存空间并将其放在原先链表头前面
- 在Java或者C++中可以使用
new
来申请空间
2.2出栈
int pop()
{
int mydata = head->data;
node* p = head;
head = head->next;
free(p);//释放内存
return mydata;
}
- C/C++语言中自己申请的内存自己释放,malloc和free一一对应,new和delete一一对应
- Java不用释放内存
2.3栈是否为空
bool isEmpty()
{
return head == NULL;
}
2.4主函数
该主函数将4~0依次入栈,然后再依次出栈。
int main(int argc, char* argv[])
{
printf("欢迎访问我的博客:http://blog.csdn.net/xuelabizp\n");
int n = 5;
while (n--)
{
printf("%d\t",n);
push(n);
}
printf("\n");
while (!isEmpty())
{
printf("%d\t",pop());
}
printf("\n");
return 0;
}
运行结果如下:
倒序输出,OK~
3.总结
- 在结点元素中可以再加一个
node*
类型的成员,每次push新数值的时候,使得新结点可以指向头结点,头结点可以指向新结点,这就是一个双向链表,当然还需要一个始终指向链表尾巴的tail - 链表的删除、插入和修改都需要遍历整个链表,找到删除或者修改的结点或者插入的位置进行操作即可,关键是删除和插入必须要处理好前后结点的关系,可以画矩形图理解
- 主流语言都有链表模板类,可以直接使用