#小菜鸡的数据结构学习之路
#仿照《大话数据结构》
#IDE VC++6.0
#include <stdio.h>
#include <string>
#include <windows.h>
#include <time.h>
#include <graphics.h>
typedef struct Node
{
int data;
struct Node *next;
}node;
typedef struct Node *LinkList; //LinkList 此时相当于一个结构体指针 后面可以直接用
/*----------固定位置的不同表达( p=(*L)->next)----------------*/
void InsertLinkList(LinkList *L,int i,int element) //!!!!一定要搞清楚自己心里的 结点位置排布 结点0在哪个位置
{
int j=1;
LinkList p,s,temp;
p=(*L)->next; //(p=(*L)->next)这样比较容易处理移动距离的问题 无论是 i= 0 1 ...
if(p && (i==0))
{
temp=(LinkList)malloc(sizeof(node));
temp->data=element;
temp->next=(*L)->next;
(*L)->next=temp;
}
while(p && j<i ) //比如i=2 (1<2) p-->第0个结点位置
{
p=p->next;
++j;
}
if(!p || j>i)
return ;
s=(LinkList)malloc(sizeof(node));
s->data=element;
s->next=p->next;
p->next=s;
}
/*-------固定位置的不同表达( p=*L)-------*/
void InsertLinkList1(LinkList *L,int i,int element) //!!!!一定要搞清楚自己心里的 结点位置排布 0在哪个位置
{
int j=0; //上面哪个是j=1 此处细品 建议画图理清思路
LinkList p,s,temp;
p=*L; // (p=*L)对比上面的(p=(*L->next)
while(p && j<i) //比如i=2
{
p=p->next;
++j;
}
if(!p || j>i)
return ;
s=(LinkList)malloc(sizeof(node));
s->data=element;
s->next=p->next;
p->next=s;
}
//删除的时候记得判断条件的选取 (p->next)
/*----------头删除-------------------------*/
void DeleteHead(LinkList *L,int *e)
{
LinkList p=(*L)->next;
if(p == NULL)
{
printf("The List is empty!\n");
return;
}
(*L)->next=p->next;
free(p);
}
/*--------------尾删除----------------------*/
void DeleteTail(LinkList *L,int *e) //这步遇到的问题是 太心急了 直接找到是要删除的
{ //这样的话 要删除的前一个的->next没有了明确的指向
LinkList p=(*L)->next; //所以还是先找前一个
LinkList q=NULL;
if(p == NULL)
{
printf("The List is empty!\n");
return;
}
while(p->next) //q保留的是要找的前一个 p是要删除的
{
q=p; //注意此时的判断条件
p=p->next;
}
*e=p->data;
if(p == ((*L)->next)) //处理只有一个结点的情况
(*L)->next=NULL;
free(p);
q->next=NULL;
}
/*-----------固定删除位置------------------*/
void DeleteFixLocal(LinkList *L,int i,int* element)
{
int j=0; //上面哪个是j=1 此处细品 建议画图理清思路
LinkList p,s,temp;
p=*L;
while(p && j<i) //比如i=2
{
p=p->next;
++j;
}
if(!p || j>i)
return ;
s=p->next; //这里已经包含了 i=0 的情况
*element=s->data;
p->next=s->next;
free(s);
}
/*---------打印链表元素----------------*/
void Print(LinkList L)
{
LinkList p;
p=L->next;
if(p==NULL)
printf("空链表");
while(p)
{
printf("%2d \t",p->data);
p=p->next;
}
printf("\n");
}
/*------------------头插法多个----------*/
void CreateListHead(LinkList *L,int n)
{
int count=10;
srand(time(0));
LinkList p;
*L=(LinkList)malloc(sizeof(node)); //记住头结点的指针的指针 用二级指针的值(*L)即一级指针(LinkList)开辟单元
(*L)->next=NULL;
for(int i=0;i<n;i++)
{
p=(LinkList)malloc(sizeof(node));
//p->data=rand()%100+1;
p->data=count;
p->next=(*L)->next;
(*L)->next=p;
++count;
}
}
/*----------单独头插一个------------------*/
void CreateListHead1(LinkList *L,int value)
{
LinkList p;
p=(LinkList)malloc(sizeof(node));
//p->data=rand()%100+1;
p->data=value;
p->next=(*L)->next;
(*L)->next=p;
}
/*---------------尾插--------------*/
void Tail(LinkList *L,int n) //自己想的
{
int count=10;
*L=(LinkList)malloc(sizeof(node));
(*L)->next=NULL;
LinkList p,s,rear;
p=(*L)->next;
for(int i=0;i<n;i++)
{
if(i==0) //如果插入的位置是第一个
{
p=(LinkList)malloc(sizeof(node));
p->data=count;
p->next=(*L)->next;
(*L)->next=p;
rear=p;
++count;
}
else //如果插入的位置是其他任意
{
s=(LinkList)malloc(sizeof(node));
s->data=count;
rear->next=s;
rear=s; //q记录即将要新插入的结点前的那个结点
++count;
}
}
}
/*-----------------尾插--------------------*/
void CreateListTail(LinkList *L,int n) //别人的
{
int count=10;
*L=(LinkList)malloc(sizeof(node));
(*L)->next=NULL;
LinkList p,q;
q=*L; //q用来记录前一个结点位置
for(int i=0;i<n;i++)
{
p=(LinkList)malloc(sizeof(node));
p->data=count;
p->next=(*L)->next;
q->next=p;
q=p;
++count;
}
q->next=NULL; //记得来处理最后的情况
}
void ClearList(LinkList *L)
{
LinkList p,q;
p=(*L)->next;
while(p->next)
{
q=p->next;
free(p);
p=q;
}
free(p);
(*L)->next=NULL;
}
void main()
{
/*
initgraph(640,640);
IMAGE img;
loadimage(&img,_T("C://Users//木歌//Pictures//001CG.bmp"));
putimage (100,100,&img);
Sleep(5000);
*/
int k=3;
LinkList L;
//CreateListHead(&L,k);
//Tail(&L,k);
CreateListTail(&L,k);
InsertLinkList(&L,0,3);
InsertLinkList(&L,1,4);
//InsertLinkList(&L,2,5);
InsertLinkList1(&L,2,5);
InsertLinkList1(&L,3,6);
CreateListHead1(&L,100);
Print(L);
DeleteHead(&L,&k);
Print(L);
DeleteTail(&L,&k);
Print(L);
DeleteFixLocal(&L,2,&k);
Print(L);
DeleteFixLocal(&L,1,&k);
Print(L);
DeleteFixLocal(&L,0,&k);
Print(L);
ClearList(&L);
Print(L);
closegraph();
printf("\n");
}
#相对上一个版本 1.增加了删除函数 2.改进了之前的插入函数
#删除的时候,注意寻找要删除的前一个,可能如果没有打印函数,就不会发现这样一个问题,如果直接删除 ,要删除的那个,它直面的那个的next指针便没有了具体的指向(可能会有个随机值),但是如果先找到前一个,再继续删除 并给前一个的next指针赋值为NULL,便可以很完美。
#插入函数,之前的版本我把i=0 ,i=1的情况单独拿出来,是因为当时还没有明白 代码的进一步含义(当然之前的代码可以实现相关功能),属于考虑不当,多做的情况,想清楚联系的时候,在修改,便会比较清爽。(这个情况也是在我补充删除函数的时候进行的尝试)
#在此,在强调一点 j=0,p=(*L)
和 j=1,p=(*L)->next 的情况 需要多思考,可以自己画图辅助。