单链表相关(一)
// 1.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <stdio.h> #include <malloc.h> #include <assert.h> typedef struct node { int data; struct node* next; }Link; //链表的建立--无头结点 int create(Link* &L,int A[],int n) { //尾插法 int i = 0; L = (Link*)malloc(sizeof(Link)); L->data = A[0]; L->next = NULL; Link* p = L; Link* q = NULL; for(i=1;i<n;i++) { q = (Link*)malloc(sizeof(Link)); if(q==NULL) return 0; q->data = A[i]; p->next = q; p = q; } q->next = NULL; return 1; } //遍历链表 void printLink(Link* L) { if(L!=NULL) { Link* p = L; while(p!=NULL) { printf("%d ",p->data); p = p->next; } printf("\n"); } } //插入---在第i个元素前插入 int Insert_Link(Link* &L,int x,int i) { if(L!=NULL && i>0) { /****************************************/ //链表的查找过程,查找第i个元素 //p指向第i个元素,q指向p的前一个元素 int j = 1; Link* p = L; Link* q = NULL; //很重要 while(p!=NULL && j<i) { j++; q = p; p = p->next; } if(p==NULL || j>i) return 0; /****************************************/ Link* T = (Link*)malloc(sizeof(Link)); T->data = x; /****************************************/ //在第一个元素前的插入操作和在其他元素前的操作有区别 //(这就是为什么有些链表会建立一个不存放数据的头结点的原因)。 if(q == NULL) //表明是在第1个元素前面进行插入的 { T->next = p; L = T; //更新链表首结点 } else //不是在第一个元素前面插入 { q->next = T; T->next = p; } /****************************************/ return 1; } return 0; } //链表的删除--删除第i个元素 int delete_Link(Link* &L,int i) { if(L!=NULL && i>0) { Link* p =L; Link* q = NULL; int k = 1; while(p!=NULL && k < i) { q = p; p = p->next; k++; } if(p==NULL || k>i) return 0; if(q==NULL) //删除的是第一个元素 { L = p->next; free(p); } else { q->next = p->next; free(p); } return 1; } return 0; } int main() { Link* L = NULL; int A[] = {1,3,2,0,9}; create(L,A,sizeof(A)/sizeof(int)); printf("建立单链表-------------:\n"); printLink(L); printf("在第一个元素前插入7-------------:\n"); Insert_Link(L,7,1); printLink(L); printf("删除第一个元素-------------:\n"); delete_Link(L,1); printLink(L); return 0; }
原以为很简单,自己写了才知道,有很多不明白的地方,俗话说“书读百遍,其义自现”,古人诚不欺我。
要注意的地方:
1、单链表无头结点和有头结点时,其插入和删除操作中,对第一个元素的操作和其他元素的操作有区别(这也就是为什么有些书上,建立单链表时会加个头结点,因为这样,对第一个元素的操作就和其他元素的操作统一起来了。)
2、注意头指针的变化情况。
//链表的就地逆置 void reverse(Link* &L) { //空表或只有一个元素 if(L==NULL || L->next==NULL) return; Link* BeforeP = NULL; Link* P = L; Link* AfterP = L->next; while(AfterP!=NULL) { P->next = BeforeP; BeforeP = P; P = AfterP; AfterP = AfterP->next; } P->next = BeforeP; L = P; }
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步