整理了双链表,双向链表结点里面含有两个指针,前指针和后指针
在对链表进行改动时要注意的头结点的前指针为NULL。
双链表的插入,删除与单链表的不同是需要判断插入的后一个结点是否为空,为空的话没有前指针
------------------------------------------------------------------------------------------------------------------
主要函数有:
求长度,插入,删除,交换,查找,清除,倒置
冒泡排序(对数据进行排序)
冒泡排序(对链表进行排序)
以下是代码:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define SEP "----------------------------------------------"
//双向链表
typedef struct node {
int data;
struct node* pre;
struct node* next;
}Node, *LinkList;
//双向链表结点的结构,里面含有两个指针
//用数组对双链表进行尾插法创建
LinkList CreateList(LinkList L, int*a, int len) {
LinkList p, q;
L = (LinkList)malloc(sizeof(Node));
L->data = 0;
L->pre = 0;//双链表头结点的前指针要指向NULL
q = L;
for (int i = 0; i < len; i++) {
p = (LinkList)malloc(sizeof(Node));
p->data = *(a + i);
q->next = p;
p->pre = q;
q = p;
}
q->next = 0;
return L;
}
void PrintList(LinkList L) {
LinkList p = L;
printf("数据\t前结点\t\t后结点\n");
while (p) {
printf("%-4d %p\t%p\n", p->data, p->pre, p->next);
p = p->next;
}
printf("%s\n", SEP);
}
//在链表的前面添加数据
LinkList addhead(LinkList L, int data) {
LinkList p = (LinkList)malloc(sizeof(Node));
p->data = data;
if (!L) {
L = p;
p->next = 0;
p->pre = 0;
}
else {
p->next = L->next;
//在这里需注意,若头结点后面的结点不为NULL时,前指针要指向插入的p
if (L->next)
L->next->pre = p;
L->next = p;
p->pre = L;
}
return L;
}
//求出当前链表的长度
int getlen(LinkList L) {
LinkList p = L;
int cnt = 0;
while (p) {
cnt++;
p = p->next;
}
return cnt;
}
LinkList getNode(LinkList L, int i) {
LinkList p = L;
for (int j = 0; j < i&&p; j++) {
p = p->next;
}
return p;
}
LinkList swap(LinkList L, int a, int b) {
int len = getlen(L);
LinkList apre, anode, anext, bpre, bnode, bnext;
if (a == b || a> len || a < 1 || b<1 || b>len)
return L;
else {
if (abs(a - b) == 1) {
if (a < b)
anode = getNode(L, a - 1);
else
anode = getNode(L, b - 1);
anext = anode->next->next;
anode->next->next = anext->next;
anext->next = anode->next;
anode->next = anext;
//先安顿好后结点,再去管前结点
if (anext->next->next) {
anext->next->next->pre = anext->next;
}
anext->next->pre = anext;
anext->pre = anode;
}
else {
//当a与b不相邻的情况
apre = getNode(L, a - 1);
bpre = getNode(L, b - 1);
anode = apre->next;
bnode = bpre->next;
anext = anode->next;
bnext = bnode->next;
apre->next = bnode;
bnode->next = anext;
bpre->next = anode;
anode->next = bnext;
if (anext)
anext->pre = bnode;
if (bnext)
bnext->pre = anode;
anode->pre = bpre;
bnode->pre = apre;
}
}
return L;
}
//长度,插入,删除,交换,查找,清除,倒置
//冒泡排序(对数据进行排序)
//冒泡排序(对链表进行排序)
//以下是链表的插入,删除,清除,与单链表的不同是需要判断插入的后一个结点是否为空,为空的话没有前指针
//插入时,若选取的结点大于链表的结点数,则把插入的值放到链表的最后面
LinkList InsertNode(LinkList L, int i, int data) {
LinkList p = L, pre, q;
for (int j = 0; j < i&&p; j++) {
pre = p;
p = p->next;
}
q = (LinkList)malloc(sizeof(Node));
q->data = data;
if (p) {
q->next = p;
q->pre = pre;
p->pre = q;
pre->next = q;
}
else {
pre->next = q;
q->pre = pre;
q->next = p;
}
return L;
}
LinkList DeleteData(LinkList L, int data) {
LinkList p = L, pre;
while (p->data != data&&p) {
pre = p;
p = p->next;
}
if (p->data == data) {
pre->next = p->next;
p->pre = pre;
if (!p)
p->next->pre = pre;
free(p);
}
else {
return L;
}
return L;
}
//让其除了头结点以外,其他结点倒置
LinkList ReverseList(LinkList L) {
LinkList p, q, temp;
p = L->next;
q = 0;
while (p) {
temp = p->next;
p->next = q;
if (q)
q->pre = p;
q = p;
p = temp;
}
L->next = q;
q->pre = L;
return L;
}
//只让链表的数据域进行交换
void BumbleSort(LinkList L) {
LinkList p = L->next;
int a[40] = { 0 }, cnt = 0;
//先把双链表的数据存到数组里面,在数组里进行交换后再返还
while (p) {
a[cnt++] = p->data;
p = p->next;
}
for (int i = 0; i < cnt; i++) {
for (int j = 0; j < cnt - 1 - i; j++) {
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
p = L->next;
for (int i = 0; i < cnt; i++) {
p->data = a[i];
p = p->next;
}
}
//让链表的结点进行交换
void BumbleSort1(LinkList L) {
LinkList p, q, temp, end;
p = L;
for (end = 0; end != L; end = temp) {
for (temp = p = L; p->next->next != end; p = p->next) {
if (p->next->data > p->next->next->data) {
q = p->next->next;
p->next->next = q->next;
q->next = p->next;
p->next = q;
temp = p->next->next;
if (q->next->next) {
q->next->next->pre = q->next;
}
q->next->pre = q;
q->pre = p;
}
}
}
}
void InitList(LinkList L, int*a, int len) {
LinkList p = L->next;
for (int i = 0; i < len; i++) {
p->data = a[i];
p = p->next;
}
}
void ClearList(LinkList L) {
LinkList p = L, q;
while (p) {
q = p->next;
free(p);
p = q;
}
p = 0;
}
int main() {
int a[] = { 23,53,21,525,5 };
int len = sizeof(a) / sizeof(int);
int num1, num2;
LinkList L = 0;//在用函数进行赋值时,一定要将声明的链表设为空值
L = CreateList(L, a, len);
//这里指针变量显示的大小有区别:64位编译器的指针是8 byte,32位编译器的指针大小是4 byte
PrintList(L);
printf("对链表的数据进行冒泡排序后(数据域版):\n");
BumbleSort(L);
PrintList(L);
printf("对链表还原后:\n");
InitList(L, a, len);
PrintList(L);
printf("对链表的结点进行冒泡排序后(结点版):\n");
BumbleSort1(L);
//L在前面已经声明了一次,故默认为L
PrintList(L);
printf("该链表倒置后:\n");
L = ReverseList(L);
PrintList(L);
printf("输入你要交换的两个结点:");
scanf("%d %d", &num1, &num2);
L = swap(L, num1, num2);
PrintList(L);
printf("输入要在链表的前面插入的数据:");
scanf("%d", &num1);
L = addhead(L, num1);
PrintList(L);
printf("输入要插入的结点位置 数据:");
scanf("%d %d", &num1, &num2);
L = InsertNode(L, num1, num2);
PrintList(L);
printf("输入你要删除的数据:");
scanf("%d", &num1);
L = DeleteData(L, num1);
PrintList(L);
return 0;
}