单链表(Singly Linked List)
单链表是比较常见的链表类型。其中每个节点都有一个指向序列下一个节点的指针。这意味着,对链表执行遍历时,只能在一个方向上从头到尾的遍历;为了能够访问链表中的最后一个节点,我们需要遍历链表中的所有元素。
单链表最后一个节点的指针域通常为NULL,在遍历到这个节点时,它指定当前链表已经结束,没有其它要遍历的节点了。
单链表的实现
定义节点
节点由两个部分组成,一个部分存储本身的数据,另一部分存储序列中下一个节点所在的内存地址。为了简单表示,我们使用一个整数作为节点的数据域,节点的数据域不仅仅局限于一个数值,可以是其它复杂的数据类型。
在C语言中,节点被定义为structure.该节点中的一个节点指向同类节点的另外一个节点。
struct Node{
int data;
struct Node *next;
} *head=NULL;
首先使用所需变量名创建一个新的节点,我们将其称之为newNode:
struct Node *newNode;
可以使用箭头字符访问存储在此Node中的数据:
newNode->data
同样的,使用执行节点的 *next 成员访问当前序列中的下一个节点:
newNode->next
头指针节点
头指针节点用于链表的第一个节点,用于标识链表的起点,并为链表的遍历提供入口。
链表的一些运算
链表的一些基本运算包括添加节点、删除节点、修改节点等等。
创建一个空链表
在执行任何操作之前,必须创建一个空链表。创建空链表时,head变量等于NULL,head变量将被用作链表的起点。
尾插法
可以通过创建新的节点,将新的节点和数据添加到链表的末尾。
遍历到列表的末尾,然后将此数据附加到链表的末尾。
void insertAtEnd(int value){
struct Node *newNode;
newNode=(struct Node*)malloc(sizeof(struct Node));
newNode->data=value;
newNode-next=NUll;
if (head==NUll){
head=newNode;
}else{
struct Node *temp=head;
while(temp->next!=null){
temp=temp->next;
}
temp->next=newNode;
}
printf("\n Node 插入成功\n");
}
头插法
将新建的节点插入到链表的头部,替换头指针,并修改该节点的连接。
void isertAtBeginning(int value){
struct Node *newNode;
newNode=(struct Node*)malloc(sizeof(struct Node));
newData->data=value;
if (head==NULL){
newNode->next=NULL;
head=newNode;
}else{
newNode->next=head;
head=newNode;
}
printf("在链表头部插入节点成功");
}
插入到链表的指定位置
通过循环遍历,可以将新节点插入到链表中的指定位置。创建一个新节点,然后将其插入链表的指定位置。
void insertPosition(int value,int pos){
int i=0;
struct Node *newNode;
newNode=(struct Node*)malloc(sizeof(struct Node));
newNode->data=value;
if (head==NULL){
newNode->next=NULL;
head=newNode;
}else{
struct Node *temp=head;
for (i=0;i<pos-1;i++){
temp=temp->next;
}
newNode->next=temp->next;
temp->net=newNode;
}
printf("链表插入节点成功");
}
从链表尾部删除节点
void removeEnd(){
if (head==NULL){
printf("链表为空");
}else{
struct Node *temp1=head,*temp2;
if (head->next==NULL){
head=NULL;
}else{
while(temp1->next!=NULL){
temp2=temp1;
temp1=temp1->next;
}
temp2->next=NULL;
}
free(temp1);
printf("从链表结尾删除节点成功");
}
}
从链表头部删除节点
void removeBehinning(){
if (head==NULL){
printf("链表为空");
}else{
struct Node *temp=head;
if (head->next==NULL){
head=NULL;
free(temp);
}else{
head=temp->next;
free(temp);
printf("从链表头部删除节点成功");
}
}
}
从链表指定位置删除节点
void removePosition(int pos){
int i,flag=1;
if (head==NULL){
printf("当前链表为空");
}else{
struct Node *temp1=head,*temp2;
if (pos==1){
head=temp1->next;
free(temp1);
printf("节点已经删除");
}else{
for (i=0;i<pos-1;i++){
if (temp1 -> next != NULL) {
temp2 = temp1;
temp1 = temp1 -> next;
}
else {
flag = 0;
break;
}
}
if (flag) {
temp2 -> next = temp1->next;
free(temp1);
printf("\nNode deleted\n\n");
}
else {
printf("删除位置错误");
}
}
}
}
链表查找
通过遍历链表来查找与给定条件符合的节点。由于只能线性访问节点,因此在这种情况下只能通过线性的方式来访问节点。这就是相较于数组,链表不支持随机访问的缺点之一。
void search(int key)
{
while (head != NULL)
{
if (head->data == key)
{
printf("找到值\n");
return;
}
head = head->next;
}
printf("未发现值\n");
}
来源:CSDN
作者:Sun.ME
链接:https://blog.csdn.net/JianZuoGuang/article/details/104318010