-创建,插入,反转链表-
/*关于链表的一系列操作*/
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}Node,*linklist;
int main(){
//创建链表,赋值 (头插法)
linklist head = (linklist)malloc(sizeof(Node));//head 头结点
linklist p = (linklist )malloc(sizeof(linklist ));//p 工具节点
head -> next = NULL;
int n;
printf ("输入要建立的链表长度:\n");
scanf ("%d", &n);
printf ("要输入的数字们:\n");
while((n--) > 0){
linklist p = (linklist )malloc(sizeof(linklist ));
scanf("%d", &p -> data);
p -> next = head -> next;
head -> next = p;
}
//打印链表
printf("\n生成的链表:\n");
p = head -> next;
while(p){
printf("%-5d",p -> data);
p = p -> next;
}
//在第n个位置插入数字 x
printf("\n*接下来插入一个数字* \n\n要在第几个位置插入数字:\n");
scanf("%d", &n);
int x;
printf("插入的数字:\n");
scanf("%d", &x);
p = head;
linklist pre = (linklist )malloc(sizeof(linklist ));//pre 标记目标结点的前一个结点
n--;
while(n!=0){
p = p -> next;
n--;
}
pre = p;
linklist s = (linklist )malloc(sizeof(linklist ));//s 储存目标数字
s -> data = x;
s -> next = pre -> next;
pre -> next = s;
//打印链表
printf("\n插入后的新链表:\n");
p = head -> next;
while(p){
printf("%-5d",p -> data);
p = p -> next;
}
//三指针法反转这个链表
pre = NULL;//指针1
linklist cur = (linklist )malloc(sizeof(linklist ));//指针2
cur = head -> next;
while(cur){
linklist next = (linklist )malloc(sizeof(linklist ));//指针3
next = cur -> next;
cur -> next = pre;
pre = cur;
cur = next;
}
head -> next = pre;
printf("\n\n反转链表 结果是:\n");
//打印链表
p = head -> next;
while(p){
printf("%-5d",p -> data);
p = p -> next;
}
}
对于头插法和尾插法:链表尾插法是从链表头开始赋值,头插法则是从链表尾开始赋值。如对于一个长度为5的链表,输入1,2,3,4,5,尾插法打印出来的是1,2,3,4,5,头插法打印出来就是5,4,3,2,1。在建立时,头插法相对于尾插法可以少定义一个变量,个人觉得更方便一些。
对于链表的查找与插入:找到目标结点的上一个结点再进行操作即可,注意使用一个指针来记录目标结点防止丢失链表。
对于反转链表:这里使用三指针法反转链表。指针cur为操作指针,负责反转每个结点,指针pre记录前一结点,用于给操作指针定位。指针next记录后一结点,给操作指针引路(记录下一结点)。每次反转一个结点就让三个指针都后移一位。
这里有个点要注意,就是控制循环终止的条件为while(cur)而不是while(pre)或while(next)。因为next总是先与cur一个结点,用next来控制会导致最后一个结点没有反转。
-合并有序链表,及销毁-
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int data;
struct node *next;
}Node,*linklist;
//尾插法创建链表
void CreatTail(linklist head)
{
Node *p,*s;
p = head;
int n;
printf("要输入几个数字:\n");
scanf("%d",&n);
printf("输入你要输入的数字们 (从小到大):\n");
while(n>0)
{
s = (Node *)malloc(sizeof(Node));
scanf("%d",&s->data);
s -> next = NULL;
p -> next = s;
p = s;
n--;
}
printf("\n");
}
int main(){
//合并有序链表
printf("\n\n*接下来合并有序链表*\n\n输入两个有序链表:\n");
linklist head1 = (linklist)malloc(sizeof(Node));
linklist head2 = (linklist)malloc(sizeof(Node));
linklist head3 = (linklist)malloc(sizeof(Node));
printf("\n*定义链表1*\n");
CreatTail(head1);
printf("\n*定义链表2*\n");
CreatTail(head2);
linklist p1 = head1 -> next;
linklist p2 = head2 -> next;
linklist p3;
if(p1 -> data < p2 -> data){
head3 = p1;
p1 = p1 -> next;
}
else{
head3 = p2;
p2 = p2 -> next;
}
p3 = head3;//此时head3直接指向第一个结点。
while(p1&&p2){
if(p1 -> data <= p2 -> data){
p3 -> next = p1;
p3 = p1;
p1 = p1 -> next;
}
else{
p3 -> next = p2;
p3 = p2;
p2 = p2 -> next;
}
}
if(p1!=NULL){
p3 -> next = p1;
}
else{
p2 -> next = p2;
}
//打印新链表
printf("合成的新链表:\n");
p = head3;
while(p){
printf("%-5d",p -> data);
p = p -> next;
}
//销毁链表
p = head3;
linklist q = p;
while(p)
{
p = p -> next;
free(q);
q = p;
}
head3 -> next = NULL;
}
对于合并有序链表:基本思路就是另设一个头结点,再设两个标记指针p1和p2来遍历,引导合并待合并链表。当其中一个指针为空时,说明有一个链表已全部合并,说明另一个链表剩下的数都是更大的数,接下来让p指向另一个链表就行。