单链表的建立
开头
首先这里介绍的建立单链表是有头结点的,因为对于带头结点的单链表,任何一个含有元素的结点都有前驱结点,在表的任何结点之前进行插入结点或删除结点,所要做的都是修改前一结点的指针域。若链表没有头结点,则首元素结点没有前驱结点,那么在其前面插入结点或删除该结点时操作会复杂些。
头插法:
思想:从一个空表开始,重复读入数据,生成新结点,将读入数据存放到新结点的数据域中,然后将新结点插入到当前链表的表头结点之后,直至读入结束标志为止(以下例子结束标志为输入-1)
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct LinkList
{
int data;
struct LinkList *next;
}Node;
//头插法建立单链表
Node *Create_Head()
{
Node *L;
Node *pNew;
int x;
L=(Node*)malloc(sizeof(Node));
L->next=NULL;
scanf("%d",&x);
while(x!=-1)//表示输入-1结束
{
pNew=(Node*)malloc(sizeof(Node));
pNew->data=x;
pNew->next=L->next;//关键代码
L->next=pNew;//关键代码
scanf("%d",&x);
}
return L;
}
void Output(Node *L)
{
Node *p;
p=L->next;
while(p)
{
printf("%d ",p->data);
p=p->next;
}
}
int main(void)
{
Node *L;
printf("开始建立单链表L,输入-1结束: \n");
L=Create_Head();
Output(L);
return 0;
}
运行结果如图:
由运行结果易知由头插法建立的单链表的元素与输入元素顺序是颠倒的,头插法这一特性常运用于单链表的逆置。
尾插法:
思想:与头插法不同,尾插法每次将创建的新结点插到当前单链表的表尾结点之后,所以要增加一个尾指针r,使之指向当前单链表的表尾。
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct LinkList
{
int data;
struct LinkList *next;
}Node;
//尾插法建立单链表
Node *Create_Tail()
{
Node *L;
Node *pNew,*r;
int x;
L=(Node*)malloc(sizeof(Node));
L->next=NULL;
r=L;
scanf("%d",&x);
while(x!=-1)
{
pNew=(Node*)malloc(sizeof(Node));
pNew->data=x;
//pNew->next=r->next;
r->next=pNew;//关键代码
r=pNew;//关键代码,尾指针移动
scanf("%d",&x);
}
r->next=NULL;
return L;
}void Output(Node *L)
{
Node *p;
p=L->next;
while(p)
{
printf("%d ",p->data);
p=p->next;
}
}
int main(void)
{
Node *L;
printf("开始建立单链表L,输入-1结束: \n");
L=Create_Tail();
Output(L);
return 0;
}
运行结果如图:
由运行结果易知由尾插法建立的单链表的数据与输入时候的数据顺序相同,因此尾插法常应用于单链表的合并。
(尾插法建立单链表)无头结点
Node *Create_Tail() {
Node *L = NULL;
Node *pNew, *r;
int x;
r = L;
scanf("%d",&x);
while(x != -1) {
pNew = (Node*)malloc(sizeof(Node));
pNew->data = x;
if (L == NULL) {
L = pNew;
r = pNew;
} else {
r->next = pNew;//关键代码
r = pNew;//关键代码,尾指针移动
}
scanf("%d",&x);
}
r->next = NULL;
return L;
}
应用
头插法应用:单链表就地逆置
尾插法应用:单链表的合并
#include <stdio.h>
#include "stdlib.h"
typedef struct linkList {
int data;
struct linkList *next;
}linkList;
//尾插法建立单链表
linkList *CreateList_Tail() {
linkList *L, *pNew, *r;
int x;
L = (linkList *)malloc(sizeof(linkList));
L->next = NULL;
r = L;
scanf("%d", &x);
while (x != -1) {
pNew = (linkList *)malloc(sizeof(linkList));
pNew->data = x;
pNew->next = r->next;
r->next = pNew;
r = pNew;
scanf("%d", &x);
}
r->next = NULL;
return L;
}
void Output(linkList *L) {
linkList *p;
p = L->next;
while (p) {
printf("%d\n", p->data);
p = p->next;
}
}
//头插法应用:单链表就地逆置
linkList *Reverse(linkList *L) {
linkList *p, *q;
p = L->next;
L->next = NULL;
while (p) {
q = p;
//注意这句话必须写在这里,不能写在结尾
//原因自己可以画个图就知道了
//如果写在结尾只能打印出一个值
//提示:p只是一个指针。
p = p->next;
q->next = L->next;
L->next = q;
}
return L;
}
//尾插法应用:单链表合并
linkList *MergeList(linkList *LA, linkList *LB) {
linkList *pa, *pb, *pc, *r;
pa = LA->next;
pb = LB->next;
LA->next = NULL;
LB->next = NULL;
pc = LA;
r = pc;
while (pa && pb) {
if (pa->data <= pb->data) {
r->next = pa;
r = pa;
pa = pa->next;
} else {
r->next = pb;
r = pb;
pb = pb->next;
}
}
if (pa) {
r->next = pa;
} else {
r->next = pb;
}
free(LB);
return pc;
}
int main(int argc, const char * argv[]) {
// insert code here...
linkList *LA, *LB, *LC;
printf("建立第一个链表:\n");
LA = CreateList_Tail();
Output(LA);
printf("建立第二个链表:\n");
LB = CreateList_Tail();
Output(LB);
//逆置(头插法应用)
//LA = Reverse(LA);
//Output(LA);
//合并(尾插法应用)
LC = MergeList(LA, LB);
Output(LC);
return 0;
}
其他
循环链表
#import <Foundation/Foundation.h>
#include<stdio.h>
#include<stdlib.h>
typedef struct LinkList {
int data;
struct LinkList *next;
}Node;
Node *Create_Tail(void);
//尾插法建立单链表
Node *Create_Tail() {
Node *L;
Node *pNew, *r;
int x;
L = (Node*)malloc(sizeof(Node));
L->next = NULL;
r = L;
scanf("%d",&x);
while(x != -1) {
pNew = (Node*)malloc(sizeof(Node));
pNew->data = x;
//pNew->next=r->next;
r->next = pNew;//关键代码
r = pNew;//关键代码,尾指针移动
scanf("%d",&x);
}
r->next = L;
return r;
}
void Output(Node *L) {
Node *p;
p = L->next->next;
while(p != L->next) {
printf("%d ",p->data);
p = p->next;
}
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
Node *L;
printf("开始建立单链表L,输入-1结束: \n");
L=Create_Tail();
Output(L);
}
return 0;
}
双向链表
#import <Foundation/Foundation.h>
typedef struct Linklist {
int data;
struct Linklist *prev;
struct Linklist *next;
}Linklist;
Linklist *CreateList() {
Linklist *head, *p, *q;
int x;
head = (Linklist *)malloc(sizeof(Linklist));
head->next = NULL;
head->prev = NULL;
p = head;
scanf("%d", &x);
while (x != -1) {
q = (Linklist *)malloc(sizeof(Linklist));
q->data = x;
p->next = q;
head->prev = q;
q->prev = p;
q->next = head;
p = q;
scanf("%d", &x);
}
return head;
}
//第一种遍历
void Output(Linklist *head) {
Linklist *L = head->next;
while (L != head) {
printf("%d ", L->data);
L = L->next;
}
}
//第二种遍历
//void Output(Linklist *head) {
// Linklist *L = head->prev;
// while (L != head) {
// printf("%d ", L->data);
// L = L->prev;
// }
//}
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
Linklist *LA;
printf("开始创建单链表(输入-1结束):\n");
LA = CreateList();
Output(LA);
}
return 0;
}
链表排序(冒泡)
//这个是没有头结点。
//有头结点也很简单
//把 Node *p = L->next改成这样就行了。
void BubbleSort(Node *L) {
for (Node *p = L; p != NULL; p = p->next) {
for (Node *q = p->next; q != NULL; q = q->next) {
if (p->data > q->data) {
int t = q->data;
q->data = p->data;
p->data = t;
}
}
}
Output(L);
}