书上的代码有些不能在编译器上面通过,会导致编译错误,我使用的编译器的是DEV C++编译器,
这个是头文件
在这里插入代码片
```typedef struct{
int age;
char name,sex,address;
}DATA;
typedef struct{
DATA *data;
int length;
}LinearList;
typedef struct node{
DATA data;
struct node *next;
}LinkedList;
typedef struct Node{
DATA data;
struct Node *next,*prior;
}DLinkedList;
这里是链表的操作封装代码:
```c
在这里插入代码片
```#include<stdio.h>
#include<stdlib.h>
#include"LinearTable.h"
LinkedList *InitLinkedList();
int GetLength(LinkedList *list);
LinkedList *GetLinkedList(LinkedList *list,int i);
int GetLocation(LinkedList *list,DATA data);
void DeleteLinkedList(LinkedList *list,DATA data);
void InsertLinkedList(LinkedList *list,int i);
void DeleteRepeat(LinkedList *list);
int main(void) {
return 0;
}
//初始化链表
//新建一个链表指针,并指向头结点,头节点由malloc()函数动态生成
//将指向头节点的下一个指针位置置空
LinkedList *InitLinkedList() {
LinkedList *list=(LinkedList*)malloc(sizeof(LinkedList));
list->next=NULL;
return list;
}
//获取链表长度
//定义一个工作指针,指向链表的头节点
//如果头节点不为空,则将头节点的一下个地址赋值给工作指针,并将计数器自增
int GetLength(LinkedList *list) {
LinkedList* workPointer=list;
int length=0;
while(workPointer->next!=NULL) {
length++;
workPointer=workPointer->next;
}
return length+1;
}
//根据指定位置读取链表元素
//定义一个工作指针,指向链表的头节点,一个计数器
//如果计数器小于指定的位置且工作指针的地址不为空不,就将计数器自增,工作指针自动指向下一个结点
//如果计数器等于指定位置,就返回工作指针,否则没有找到
LinkedList *GetLinkedList(LinkedList *list,int i) {
LinkedList *workPointer=list->next;
int count=1;
while(count<i&&workPointer!=NULL) {
workPointer=workPointer->next;
count++;
}
if(count==i) return workPointer;
else return NULL;
}
//根据给出的数据类型在链表中查找该元素的位置
//建立一个工作指针,指向头节点,比较头节点所指的首结点数据元素,不相等,就将工作指针自动指向下一个结点
//如果指向的地址不为空,就返回该地址的位置,否则返回 0
int GetLocation(LinkedList *list,DATA data) {
int location=1;
LinkedList *workPointer=list->next;
while((list->next)->data.age!=data.age&&(list->next)->data.name!=data.name&&(list->next)->data.address!=data.address&&(list->next)->data.sex!=data.sex) {
workPointer=workPointer->next;
location++;
}
if(workPointer!=NULL) return location;
else return 0;
}
//根据指定位置插入相应的数据元素
//定义一个工作指针,临时指针(用来保存动态生成的结点地址)
//判断,如果插入位置为1,就直接将工作指针指向头节点,否则,将指针指向i的上一个结点,并将节点的数据域赋值
//将工作指针指向结点的地址域赋值给临时指针的地址域,再将临时指针赋值给工作指针指向结点的地址域
void InsertLinkedList(LinkedList *list,int i,DATA data) {
LinkedList *workPointer,*temp;
if(i==1) workPointer=list;
else workPointer=GetLinkedList(list,i-1);
if(workPointer==NULL) printf("not find");
else {
temp=(LinkedList*)malloc(sizeof(LinkedList));
temp->data=data;
temp->next=workPointer->next;
workPointer->next=temp;
}
}
//根据指定位置删除节点,定义一个工作指针,临时指针(指向待删除的结点)
//判断删除位置,如果i==1就将工作指针指向头节点,临时指针指向首节点,否则将工作指针指向i的上一个结点,临时指针指向待删除结点
//如果工作指针指向地址不为空,且指向地的下一个地址不为空 ;将临时指针的地址域赋值给工作指针的下一个地址域,并释放临时指针
void DeleteLinkedList(LinkedList *list,int i) {
LinkedList *workPointer,*temp;
if(i==1) {
workPointer=list;
temp=list->next;
} else {
workPointer=GetLinkedList(list,i-1);
temp=GetLinkedList(list,i);
}
if(workPointer!=NULL&&workPointer->next!=NULL) {
workPointer->next=temp->next;
free(temp);
} else {
printf("not find this data");
}
}
//删除重复结点:
//总共定义三个指针:
//第一个指针指向链表的首节点,第二个指针指向第一个指针的下一个结点,第三个指针为临时指针保存第二个指针
//外层: 第一个指针指向链表的首节点,当指针不为空时,
// 内层:将第一个指针和第二个指针的数据域进行比较,如果相等,就创建临时指针变量保存第二指针,将第二指针的地址域指向临时指针的下一个地址域
// 释放临时指针 ,同时将工作指针向后移动
//将指针移动到下一个链表结点
void DeleteRepeat(LinkedList *list) {
LinkedList *workOuterPointer=list->next,*workInnerPointer=workOuterPointer->next;
while(workOuterPointer!=NULL) {
while(workInnerPointer!=NULL) {
if(workOuterPointer->data.age==workInnerPointer->data.age&&workOuterPointer->data.name==workInnerPointer->data.name&&
workOuterPointer->data.sex==workInnerPointer->data.sex&&workOuterPointer->data.address==workInnerPointer->data.address
) {
LinkedList *temp=workInnerPointer;
workInnerPointer->next=temp->next;
free(temp);
workInnerPointer=workInnerPointer->next;
} else {
workInnerPointer=workInnerPointer->next;
}
}
}
workOuterPointer=workOuterPointer->next;
}
这里是双向循环链表表的实现,这里只做链表插入和删除,其余的和操作和单链表出入不大
```c
在这里插入代码片
``#include<stdio.h>
#include<stdlib.h>
#include"LinearTable.h"
//双向循环列表的代码:和教材上面有些出入,教材上面的代码描述,可能无法在编译器上面通过
//双向列表的结构:结点有直接接前驱指针prior,直接后继指针next;
void DeleteDLinkedList(DLinkedList *dlist,int i);
DLinkedList *GetDLinkedList(DLinkedList *dlist,int i);
void InsertDLinkedList(DLinkedList *dlist,int i,DATA data);
int main(void) {
return 0;
}
//双向循环链表表的删除:定义一个工作指针,和临时指针变量 (用来保存待删除结点)
//将 临时指针变量直接后继的前驱指向工作指针,将工作指针的的后继指针指向临时指针变量的直接后继
//释放掉临时指针变量
void DeleteDLinkedList(DLinkedList *dlist,int i) {
DLinkedList *temp=GetDLinkedList(dlist,i),*workPointer=temp->prior;
workPointer->next=temp->next;
workPointer=temp->next->prior;
free(temp);
}
DLinkedList *GetDLinkedList(DLinkedList *dlist,int i){
DLinkedList *workPointer=dlist->next;
int location=1;
while(location<i&&workPointer!=NULL) {
workPointer=workPointer->next;
location++;
}
if(location==i) return workPointer;
else return NULL;
}
//双向循环链表 的插入:定义一个工作指针,和临时指针变量(用来保存插入数据)
//如果插入位置是链表的第一个结点,否则时第个结点,这里使用尾插法,插入到第I个节点之后,前插后插都一样
//判断工作指针地址是否为空(因为这里的GEt函数获取的值可能为空),否则就提示插入错误
//不为空;申请一个动态节点,并用临时指针变量保存地址,临时指针变量数据域赋值数据,将指针变量直接后继地址==工作指针的直接后继地址,并将后继地址的直接前驱指向临时指针变量
//,将工作指针的直接后继指向临时指针变量,将临时指针变量的直接前驱指向工作指针
void InsertDLinkedList(DLinkedList *dlist,int i,DATA data){
DLinkedList *workPointer,*temp;
if(i==1) workPointer=dlist->next;
else workPointer=GetDLinkedList(dlist,i);
if(workPointer!=NULL){
temp=(DLinkedList*)malloc(sizeof(DLinkedList));
temp->data=data;
temp->next=workPointer->next;
temp=temp->next->prior;
temp=workPointer->next;
workPointer=temp->prior;
}else{
printf("Insert error") ;
}
}`