第三周学习

一、链表

1、带头指针的链表

上周学习malloc函数申请的空间一般为连续的,这种方式一般会产生很多碎片空间,他的查找效率较高,但插入和删除操作很慢;

为了尽可能的利用这些碎片空间,同时学习一种插入和删除都很便利的存储方式,开始学习链表相关知识;

使用方法:

  1 #include <stdio.h>
  2 
  3 struct node
  4 {
  5     int data;//数据域
  6     struct node *next;//指针域,保存下一个节点的地址
  7 };
  8 
  9 int main()
 10 {
 11     struct node* head=NULL,*pnew=NULL;
 12     struct node *tail=NULL;//指向最后一个节点的地址
 13     
 14     pnew->data=1001;
 15     pnew->next=NULL;
 16 
 17     if(head==NULL)
 18     {   
 19         head=pnew;
 20         tail=pnew;
 21     }else
 22     {
 23         tail->next=pnew;//前一个节点的指针域指向后一个节点
 24         tail=pnew;//最后一个节点的地址tail保存
 25     }
 26     
 27     printf("%d\t%p\n",p->data,p->next);
 28     
 29     return 0;
 30 }

尾插法,插入链表,要调用时,知道头指针即可遍历所有链表;

头插法为:

pnew->next=head;

head=pnew;

对链表进行相关操作:

1、释放链表

void free_room(STU** head)
{
    STU* p=NULL;
    
    while(*head!=NULL)
    {   
        p=*head;
        *head=(*head)->next;
        free(p);
    }   

    return;    
}

2、排序操作

思路:从链表找出最大值,然后通过头插法加入新的链表;

分成三步:

a、从旧链表中找出最大值

b、将最大值从旧链表中移下来

c、通过头插法将移下来的节点,通过头插法形成新的链表


//1、从旧链表中找出最大值
struct node* find_max_from_oldlist(struct node *head)
{
        struct node *p = head, *pmax = head;

        while(p != NULL)
        {
                if(p->data > pmax->data)
                {
                        pmax = p;
                }
                p = p->next;
        }
        return pmax;
}

//2、将最大值从旧链表中移下来
struct node* remove_max_from_oldlist(struct node *head, struct node *pmax)
{
        if(head == pmax) //头部移除
        {
                head = head->next;
        }
        else  //其他位置移除
        {
                struct node *p = head;
                while(p->next != pmax)
                {
                        p = p->next;
                }

                p->next = pmax->next;
        }
        return head;
}

//3、将移下来的最大值通过头插法加入新的链表
struct node* add_newlist(struct node* new_head, struct node *pmax)
{
        pmax->next = new_head;
        new_head = pmax;
        return new_head;
}

//链表的排序操作
struct node* list_sort(struct node *head)
{
        struct node *new_head = NULL;
        struct node *pmax = NULL;

        while(head!=NULL)
        {
                //1、从旧链表中找出最大值
                pmax = find_max_from_oldlist(head);

                //2、将最大值从旧链表中移下来
                head = remove_max_from_oldlist(head, pmax);

                //3、将移下来的最大值通过头插法加入新的链表
                new_head = add_newlist(new_head, pmax);
        }
        return new_head;
}

二、快速排序算法的实现

本周学习了多种排序算法,但大多时间复杂度均为n的平方,耗时较长,快速排序算法的时间复杂度为nlog n相对较快,且理解较难,所以特此记录,并写下代码

  1 #include <stdio.h>
  2 
  3 /*
  4  *函数功能:让第一个函数为基准值,前后进行排序,小的放左边,大的放右边
  5  *然后找出基准值位置
  6  *
  7  *传递参数:数组a的起始地址,起始查找地址,结尾查找地址
  8  *
  9  *返回值:返回基准值的地址下标
 10  *
 11  *其他说明:先比较high与基准值,大则自减,小则让low的值为high,然后
 12  *同理操作i
 13 */
 14 int find_adr(int a[],int low,int high)
 15 {   
 16     int key=a[low];
 17     while(low<high)
 18     {
 19         while(low<high&&a[high]>=key)
 20         {
 21             high--;
 22         }
 23 
 24         a[low]=a[high];
 25 
 26         while(low<high&&a[low]<=key)
 27         {
 28             low++;
 29         }
 30 
 31         a[high]=a[low];
 32     }
 33     
 34     a[low]=key;
 35     
 36     return low;
 37 }
 38 
 39 /*
 40  *函数功能:快速排序功能主体,通过递归实现
 41  *
 42  *传递参数:数组a,起始地址,结尾地址
 43  *
 44  *返回值:无
 45  *
 46  *其他说明:函数出口为:low=high,然后调用find函数粗排序,同时递归调用
 47  *两边进行查找,出口均为low=high,最后完成函数功能
 48 */
 49 void quick_sort(int a[],int low,int high)
 50 {
 51     if(low<high)
 52     {
 53         int ret=find_adr(a,low,high);
 54         quick_sort(a,low,ret-1);
 55         quick_sort(a,ret+1,high);
 56     }
 57 }
 58 
 59 //O(n)=n logn时间复杂度
 60 int main()
 61 {
 62     int a[5]={5,9,2,7,1};
 63 
 64     quick_sort(a,0,4);
 65 
 66     for(int i=0;i<5;i++)
 67     {
 68         printf("%d\n",a[i]);
 69     }
 70 
 71     return 0;
 72 }
         

这种理解相对较为复杂,且在链表操作时可能会出现越界的情况,在通过学习一些更简便的思想后,对相关链表的快速排序操作进行如下理解:

/*
 *函数功能:快速排序学号
 *
 *传递函数:链表第一个元素地址与最后一个元素地址
 *
 *返回值:无
 *
 *其他说明:定义两个指针i,j均在第二个位置,比基准值小的放到i左边,大的放到i与j之间
 *遍历j,进行比较,最后将i的前一个与基准值对调;然后递归该函数
*/
void quick_sort_num(STU* pbegin,STU* pend)
{
    if(pbegin!=NULL&&pbegin->next!=NULL&&pbegin!=pend)
    {
        STU* i=pbegin->next;
        STU* i_pre=pbegin;
        STU* j=pbegin->next;

        int key=pbegin->num;
        while(j!=NULL)
        {
            if(j->num<key)
            {
                swap_element(i,j);
    
                i_pre=i;
                i=i->next;
            }
            j=j->next;  
        }

        swap_element(pbegin,i_pre);

        quick_sort_num(pbegin,i_pre);
        quick_sort_num(i,pend);
    }

    return;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值