一、C-单链表-头插/尾插法-模板
#include "stdio.h"
#include "stdlib.h"
typedef struct List {
int data; //数据域
struct List *next; //指针域
} List;
void TailCreatList(List *L) //尾插法建立链表👈
{
List *s, *r;//s用来指向新生成的节点。r始终指向L的终端节点。
r = L; //r指向了头节点,此时的头节点是终端节点。
for (int i = 0; i < 10; i++) {
s = (struct List*) malloc(sizeof(struct List));//s指向新申请的节点
s->data = i; //用新节点的数据域来接受i
r->next = s; //用r来接纳新节点
r = s; //r指向终端节点
}
r->next = NULL; //元素已经全部装入链表L中
//L的终端节点指针域为NULL,L建立完成
}
void HeadCreatList(List *L) //头插法建立链表👈
{
List *s; //不用像尾插法一样生成一个终端节点。
L->next = NULL;
for (int i = 0; i < 10; i++) {
s = (struct List*) malloc(sizeof(struct List));
s->data = i;
s->next = L->next; //将L指向的地址赋值给S;//头插法与尾插法的不同之处主要在此,
//s所指的新节点的指针域next指向L中的开始节点
L->next = s; //头指针的指针域next指向s节点,使得s成为开始节点。
}
}
void DisPlay(List *L) { //打印节点
List *p = L->next;
while (p != NULL) {
printf("%d ", p->data);
p = p->next;
}
printf("\n");
}
int main() {
List *L1, *L2;
L1 = (struct List*) malloc(sizeof(struct List));
L2 = (struct List*) malloc(sizeof(struct List));
HeadCreatList(L1);
DisPlay(L1);
TailCreatList(L2);
DisPlay(L2);
}
二、头插-删除操作-例题
题目清晰易懂,直接写:
#include <stdio.h>
#include <stdlib.h>
int cnt, x;//cnt记录节点个数,x用于data输入
//结构体节点,typedef可以使新定义结构体指针时省略关键字struct
typedef struct node
{
int data;
struct node *next;
} node;
void HeadCreatList(node *head)//传入头指针
{
node *p;
head->next = NULL;
while (1)
{
scanf("%d", &x);
if (x >= 0)
{ //标准操作
cnt++;
p = (struct node *)malloc(sizeof(struct node));
p->data = x;
p->next = head->next;
head->next = p;
}
else
{
break;//跳出
}
}
}
int main()
{
struct node *head;//定义头指针
head = (struct node *)malloc(sizeof(struct node));//这里需要给头指针开辟空间,有个地址
HeadCreatList(head);//传入
int del, pt = 0;//del为要删除的第del数,pt在输出的while中表示“当前节点排名”
scanf("%d", &del);
if (del == -1)
del = cnt;//题目要求
if (del > cnt)
printf("Node not found!\n");//题目要求
while (head->next != NULL)//注意头插与尾插的区别
{
pt++;
if (pt == del) //逻辑删除,不输出即可
{
head = head->next; //这里要记得向后移动指针!
continue;
}
else
printf("%d ", head->next->data);//头插发head是没有的data的,data存储在head指向的结构体指针(head->next)中(head->next->data)
head = head->next;//指针后移
}
//system("pause");
return 0;
}
三、头插-改值操作-例题
其实这和上面那个几乎一模一样,输出部分改一下就行了
while (head->next != NULL)
{
pt++;
if (pt == del)
head->next->data=val;
printf("%d ", head->next->data);
head = head->next;
}
可是为什么不直接输出呢,反正也不知道你改了没有/滑稽
while (head->next != NULL)
{
pt++;
if (pt == del)
printf("%d ",val);
else
printf("%d ", head->next->data);
head = head->next;
}
四、尾插-查找操作-例题
这些题都差不多的……
#include <stdio.h>
#include <stdlib.h>
//尾插链表
struct node
{
int data, rank;//值,位置
struct node *next;
};
int main()
{
int n;
while (~scanf("%d", &n))
{
//尾插基操
int cnt = 0;
struct node *head, *p1, *p2;
head = NULL;
p1 = p2 = (struct node *)malloc(sizeof(struct node));
while (1)
{
cnt++;
if (cnt == n + 1)//跳出
break;
p1->rank = cnt;//记录位置
scanf("%d", &p1->data);
(cnt == 1) ? (head = p1) : (p2->next = p1);
p2 = p1;
p1 = (struct node *)malloc(sizeof(struct node));
}
int find;//要找的值
scanf("%d", &find);
p2->next = NULL;
int f = 0;//标志变量
while (head != NULL)//这就是尾插与头插输出的不同,这里直接是head
{
if (head->data == find)//找到了
{
printf("%d %d\n", head->rank, head->data);
f = 1;//改变状态
break;
}
head = head->next;
}
if (f == 0)
printf("0\n");
}
return 0;
}
五、尾插-插入操作-例题
这个也挺简单的,就新定义一个结构体指针,赋值后在要插入的位置改下连接方式即可
①在递增有序链表中插入一个值并使其仍然保持有序
#include <stdio.h>
#include <stdlib.h>
int n, x;
typedef struct node
{
int data;
struct node *next;
} node;
node *head, *tail, *p, *newnode;
void TailCreate(int x)//尾插创建链表
{
tail->next = (struct node *)malloc(sizeof(struct node));
tail = tail->next;
tail->data = x;
tail->next = NULL;
}
void insert(int x)//插入操作
{
p = (struct node *)malloc(sizeof(struct node));
p = head;
p->data = -1;//将表头(第0号节点)赋值-1以便于当x小于第一个节点时的插入操作
while (p != NULL)
{
if (x < (p->next->data) && x > (p->data))//x小于前一个且大于后一个
{
newnode = (struct node *)malloc(sizeof(struct node));
newnode->data = x;
newnode->next = p->next;
p->next = newnode;
break;
}
p = p->next;
}
}
int main()
{
while (~scanf("%d", &n))
{
head = tail = (struct node *)malloc(sizeof(struct node));
for (int i = 1; i <= n; i++)
{
scanf("%d", &x);
TailCreate(x);
}
scanf("%d", &x);
insert(x);
head = head->next;//从0号节点移动到1号节点
while (head != NULL)
{
printf("%d ", head->data);//注意这题“间隔两个空格”
head = head->next;
}
printf("\n");
}
//system("pause");
return 0;
}
②无序输入,建立有序递增链表
其实看见这题我第一想法是用一个数组把输入先存下排序,再套上题代码就好了呀/滑稽
正儿八经的代码:
#include <stdio.h>
#include <stdlib.h>
int n, x;
typedef struct node
{
int data;
struct node *next;
} node;
node *head, *p, *newnode;
void insert(int x)//有序插入
{
p = head;//每次进入函数使p从表头开始往后走
while (p != NULL)//当p还指向链表中的节点
{
if (p->next == NULL)//如果p已经走到表尾(即下一个为NULL),x还未插入,就把x放在表尾
{
p->next = (struct node *)malloc(sizeof(struct node));
p = p->next;
p->data = x;
p->next = NULL;//NULL后移
}
else
{
if (x > p->data && x < p->next->data)//按升序插入
{
newnode = (struct node *)malloc(sizeof(struct node));
newnode->data = x;
newnode->next = p->next;//连接前后节点
p->next = newnode;
break;
}
}
p = p->next;//后移p
}
}
int main()
{
while (~scanf("%d", &n))
{
head = (struct node *)malloc(sizeof(struct node));
head->data = -1;//表头第0个节点赋值-1,方便下x<第1个节点的判断
head->next = NULL;
for (int i = 1; i <= n; i++)
{
scanf("%d", &x);
insert(x);
}
head = head->next;//跳过表头(第0个节点)
while (head != NULL)//输出
{
printf("%d ", head->data);
head = head->next;
}
printf("\n");
}
//system("pause");
return 0;
}
六、合并升序链表,并保持升序
主要是强调关于c++里申请哨兵节点的方法:
ListNode *head = new ListNode(0)
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
if(!pHead2) return pHead1;
if(!pHead1) return pHead2;
ListNode *head=new ListNode(0); //这里切勿直接head=nullptr,混淆指针与对象
ListNode *ptr=head;
while(pHead1 && pHead2)
{
if(pHead1->val < pHead2->val) ptr->next=pHead1,pHead1=pHead1->next;
else ptr->next=pHead2,pHead2=pHead2->next;
ptr=ptr->next;
}
while(pHead1) ptr->next=pHead1,pHead1=pHead1->next,ptr=ptr->next;
while(pHead2) ptr->next=pHead2,pHead2=pHead2->next,ptr=ptr->next;
return head->next;
}
};