标签:单链表
【基本概念】单链表即单向链表,数据结构为一个接一个的结点组成,每个结点有两个成员,一个数据域一个指向下一个结点的指针,如下:
struct Node
{
int data;
struct Node *next;
};
单链表基本操作包括链表初始化、插入、删除,其中初始化操作是指让单链表存在一个头结点,其数据域随机,头结点指向下一个结点,每次访问都要从头结点开始访问,插入结点方式有两种,尾部插入和结点前部插入,尾部插入很简单与正常的输入顺序一致,而前部插入需要时常变动头结点的指针,始终让他指向新插入的,因为如果不调整头指针的话,在输出时是无法从头结点往前访问的,记住,它是单向链表。删除操作主要是定值查找删除,在链表里并不需要做什么删除操作,其实就是将前一结点指针指向目标节点的下一个结点位置,指针访问时直接跳跃,即可实现删除操作。
【测试代码】
#include<stdio.h>
#include<stdlib.h>
#include<stack>
typedef int data_type;
typedef struct Node node_t;// 给struct Node取个别名node_t
typedef struct Node * node_ptr;//给struct Node*取个别名node_ptr
typedef struct Node
{
data_type data;
struct Node *node_next;//node_next是一个指向结构的指针,告诉指针要指向的地址就要付给它一个结构类型地址
};
//链表初始化
node_t * init()
{
node_ptr p;
p = (node_t *)malloc(sizeof(node_t));
p->node_next = NULL;
return p;
}
//在链表后面插入结点
node_t *insert_back(node_ptr p , data_type data)
{
node_ptr pnew = (node_t *)malloc(sizeof(node_t));
pnew ->node_next = NULL;
pnew ->data = data;
p->node_next = pnew;
return pnew;
}
void remove(node_ptr p, data_type data)
{
node_ptr find = p;
if(!find)
return ;
while(find->node_next->data !=data)
{
find= find->node_next;
}
find->node_next = find->node_next->node_next ;
}
//正常打印
void print(node_ptr p)
{
if(!p)
{
printf("no data, you think too much");
return ;
}
while(p->node_next != NULL)
{
printf("%d ", p->data);
p = p->node_next;
}
printf("%d ", p->data);
printf("\n");
}
void main()
{
node_ptr pnode, list;
pnode = init();
list = pnode;
pnode = insert_back(pnode, 1);
pnode = insert_back(pnode, 2);
pnode = insert_back(pnode, 3);
pnode = insert_back(pnode, 4);
pnode = insert_back(pnode, 5);
pnode = insert_back(pnode, 6);
printf("normal print:");
print(list->node_next);
printf("-------------------------------------------\n");
remove(list,1);
printf("remove one node 1 print:");
print(list->node_next);
printf("-------------------------------------------\n");
remove(list,2);
remove(list,3);
remove(list,4);
remove(list,5);
remove(list,6);
printf("remove all print:");
print(list->node_next);
printf("\n-------------------------------------------\n");
}
【输出】
这段测试代码中使用的是尾部插入,设置了一个指针pnode指向尾结点,指针list始终指向头结点,访问链表时从list开始,而pnode就用于插入新结点和删除结点,插入的新节点永远在尾部后面,这样要比**list形式理解起来简单一点,大部分的资料都喜欢用双重指针,但是双重指针繁杂不易理解,尤其在访问地址变换的时候,很容易出错,所以先以这种简单的方式来理解单链表的基本思想。
结点存储方式如下
以前部插入为例,设计测试代码如下:
#include<stdio.h>
#include<stdlib.h>
#include<stack>
typedef int data_type;
typedef struct Node node_t;// 给struct Node取个别名node_t
typedef struct Node * node_ptr;//给struct Node*取个别名node_ptr
typedef struct Node
{
data_type data;
struct Node *node_next;//node_next是一个指向结构的指针,告诉指针要指向的地址就要付给它一个结构类型地址
};
node_t * init()
{
node_ptr p;
p = (node_t *)malloc(sizeof(node_t));
p->node_next = NULL;
return p;
}
//链表从前面插入
node_t * insert_front(node_ptr p , data_type data)
{
p->data = data;
node_ptr pnew = (node_t *)malloc(sizeof(node_t));
pnew->node_next = p;
return pnew;
}
void remove(node_ptr p, data_type data)
{
node_ptr find = p;
if(!find)
return ;
while(find->node_next->data !=data)
{
find= find->node_next;
}
find->node_next = find->node_next->node_next ;
}
//正常打印
void print(node_ptr p)
{
if(!p)
{
printf("no data, you think too much");
return ;
}
while(p->node_next != NULL)
{
printf("%d ", p->data);
p = p->node_next;
}
printf("%d ", p->data);
printf("\n");
}
void main()
{
node_ptr pnode, list;
pnode = init();
pnode = insert_front(pnode, 1);
pnode = insert_front(pnode, 2);
pnode = insert_front(pnode, 3);
pnode = insert_front(pnode, 4);
pnode = insert_front(pnode, 5);
pnode = insert_front(pnode, 6);
list = pnode;
printf("normal print:");
print(list);
printf("-------------------------------------------\n");
remove(list,1);
printf("remove one node 1 print:");
print(list->node_next);
printf("-------------------------------------------\n");
remove(list,2);
remove(list,3);
remove(list,4);
remove(list,5);
remove(list,6);
printf("remove all print:");
print(list->node_next);
printf("\n-------------------------------------------\n");
}
【输出】
注意两个测试代码输出有什么区别,前向插入,是倒着输出的,跟输入顺序不一样。
其他单链表相关操作都是在此基础上做的,忘记了单链表怎么操作时可以参考的
标签:单链表
原文地址:http://blog.csdn.net/xinyu913/article/details/45846833