【筆記】直接插入排序

Time-space發表於2017-11-03

  插入排序的演算法思想:將待排序元素分為已排序子集和未排序子集,一次從未排序子集中的一個元素插入已排序子集中,使已排序自己仍然有序;重複執行以上過程,指導所有元素都有序為止。

  直接插入排序是一種最簡單的插入排序演算法。

1.陣列實現

  基本演算法思想:把被排序的記錄逐個取出,插在適當的位置。即進行第i遍整理時,前i-1個記錄A[1],A[2],…,A[i-1],已經排序順序;取出第i個記錄A[i],在整理好的序列中為A[i]找到一個合適的位置j,即A[1],A[2],…,A[j-1]的關鍵字都小於或等於A[i]的關鍵字,而A[j],…,A[i-1]中的關鍵字都大於A[i]的關鍵字;將從j開始到位置i-1的記錄全部後移一步;將原來A[i]中的資料插在A[j];於是,A[1],A[2],…,A[i]仍然是排好順序的。

  例如給定一個含有8個元素的元素,對應的關鍵字序列為(45,23,56,12,97,76,29,68),將這些元素按照關鍵字從小到大進行直接插入排序的過程如下圖所示。


這裡寫圖片描述

  • 型別定義
#define MaxSize 100
typedef int KeyType;
typedef struct /*資料元素型別定義*/
 {
    KeyType key;/*關鍵字*/
}DataType;
typedef struct /*順序表型別定義*/
 {
    DataType data[MaxSize];
    int length;
}SqList;
  • 直接插入排序函式
void InsertSort(SqList *L)
/*直接插入排序*/
{
    int i,j;
    DataType t;
    for(i=1;i<L->length;i++)        /*前i個元素已經有序,從第i+1個元素開始與前i個有序的關鍵字比較*/
    {
        t=L->data[i+1];             /*取出第i+1個元素,即待排序的元素*/
        j=i;
        while(j>0&&t.key<L->data[j].key)/*尋找當前元素的合適位置*/
        {
            L->data[j+1]=L->data[j];
            j--;
        }
        L->data[j+1]=t;             /*將當前元素插入合適的位置*/
    }
}
  • 主程式
#include<stdio.h>
#include<stdlib.h>
void InitSeqList(SqList *L,DataType a[],int n)
/*順序表的初始化*/
{
    int i;
    for(i=1;i<=n;i++)
    {
        L->data[i]=a[i-1];
    }
    L->length=n;
}
void DispList(SqList L,int n)
/*順序表的輸出*/
{
    int i;
    for(i=1;i<=n;i++)
        printf("%4d",L.data[i].key);
    printf("\n");
}
void main()
{
    DataType a[]={78,29,45,10,80,21,55,3,60,32};
    int delta[]={5,3,1};
    int n=10,m=3;
    SqList L;
    InitSeqList(&L,a,n);
    printf("[排序前]          ");
    DispList(L,n);
    InsertSort(&L);
    printf("[直接插入排序結果]");
    DispList(L,n);
}

2.連結串列實現

  基本演算法思想:首先建立一個連結串列,將待排序元素依次插入連結串列中。將待排序的連結串列分為兩個部分,即有序序列和待排序序列。初始時,有序序列中沒有元素,令L->next=NULL。指標p指向待排序的連結串列,若有序序列為空,將p指向的第一個結點插入空連結串列L中。然後將有序連結串列即L指向的連結串列的每一個結點與p指向的結點比較,並將結點*p插入L指向的連結串列的恰當位置。重複執行上述操作,指導待排序連結串列為空。此時,L就是一個有序連結串列。

  • 連結串列標頭檔案
void InitList(LinkList *h)
/*單連結串列的初始化*/
{
if((*h=(LinkList)malloc(sizeof(ListNode)))==NULL)       /*為頭結點分配一個儲存空間*/
exit(-1);
(*h)->next=NULL;                /*將單連結串列的頭結點指標域置為空*/
}
int ListEmpty(LinkList h)   
/*判斷單連結串列是否為空*/
{
    if(h->next==NULL)           /*如果連結串列為空*/
        return 1;               /*返回1*/
    else                        /*否則*/
        return 0;               /*返回0*/
}
ListNode *Get(LinkList h,int i)   
/*查詢單連結串列中第i個結點。查詢成功返回該結點的指標,否則返回NUL*/
{
ListNode *p;
int j;
if(ListEmpty(h))        /*查詢第i個元素之前,判斷連結串列是否為空*/
    return NULL;
   if(i<1)              /*判斷該序號是否合法*/
        return NULL;
    j=0;
p=h;
while(p->next!=NULL&&j<i)
{
    p=p->next;
    j++;
}
if(j==i)            /*如果找到第i個結點*/
    return p;       /*返回指標p*/
else;               /*否則*/
    return NULL ;/*返回NULL*/
}
ListNode *LocateElem(LinkList h,DataType e)   
/*查詢線性表中元素值為e的元素,查詢成功返回對應元素的結點指標,否則返回NULL */
{
ListNode *p;
p=h->next;      /*指標p指向第一個結點*/
while(p)
{
    if(p->data!=e)  /*如果當前元素值與e不相等*/
        p=p->next;  /*則繼續查詢*/
    else            /*否則*/
        break;      /*退出迴圈,停止查詢*/
}
return p;           /*返回結點的指標*/
}
int LocatePos(LinkList h,DataType e)   
/*查詢線性表中元素值為e的元素,查詢成功返回對應元素的序號,否則返回0*/
{
ListNode *p;
int i;
if(ListEmpty(h))        /*查詢第i個元素之前,判斷連結串列是否為空*/
    return 0;
p=h->next;      /*從第一個結點開始查詢*/
i=1;
while(p)
{
    if(p->data==e)  /*找到與e相等的元素*/
        return i;   /*返回該序號*/
    else            /*否則*/
    {
        p=p->next; /*繼續查詢*/
        i++;
    }
}
if(!p)              /*如果沒有找到與e相等的元素,返回0,表示失敗*/
    return 0;
}
int InsertList(LinkList h,int i,DataType e)
/*在單連結串列中第i個位置插入值e的結點。插入成功返回1,失敗返回0*/
{
ListNode *p,*pre;   
int j;
pre=h;          /*指標p指向頭結點*/
j=0;
while(pre->next!=NULL&&j<i-1)/*找到第i-1個結點,即第i個結點的前驅結點*/
{
    pre=pre->next;
    j++;
}
if(j!=i-1)                  /*如果沒找到,說明插入位置錯誤*/
{
    printf("插入位置錯");
    return 0;
}
/*新生成一個結點,並將e賦值給該結點的資料域*/
if((p=(ListNode*)malloc(sizeof(ListNode)))==NULL)
    exit(-1);
p->data=e;
/*插入結點操作*/
p->next=pre->next;
pre->next=p;
return 1;
}
int DeleteList(LinkList h,int i,DataType *e)
/*刪除單連結串列中的第i個位置的結點。刪除成功返回1,失敗返回0*/
{
ListNode *pre,*p;
int j;
    pre=h;
    j=0;
    while(pre->next!=NULL&&pre->next->next!=NULL&&j<i-1)/*在尋找的過程中確保被刪除結點存在*/
    {
        pre=pre->next;
        j++;
    }
    if(j!=i-1)              /*如果沒找到要刪除的結點位置,說明刪除位置錯誤*/
    {
        printf("刪除位置錯誤");
        return 0;
}
    p=pre->next;
*e=p->data;
/*將前驅結點的指標域指向要刪除結點的下一個結點,也就是將p指向的結點與單連結串列斷開*/
    pre->next=p->next;
    free(p);                /*釋放p指向的結點*/
    return 1;
}
int ListLength(LinkList h)
/*求線性表的表長*/
{
    ListNode *p;
    int count=0;
    p=h;
    while(p->next!=NULL)
    {
        p=p->next;
        count++;
    }
    return count;
}
void DestroyList(LinkList h)
/*銷燬連結串列*/
{
    ListNode *p,*q;
    p=h;
    while(p!=NULL)
{
    q=p;
        p=p->next;
        free(q);
    }
}
  • 型別定義
typedef int DataType;   /*元素型別定義為整型*/
typedef struct Node     /*單連結串列型別定義*/
{
    DataType data;
    struct Node *next;
}ListNode,*LinkList;
  • 主程式
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include"LinkList.h"

void CreateList(LinkList L,DataType a[],int n)
/*創建單連結串列*/
{
    int i;
    for(i=1;i<=n;i++)
        InsertList(L,i,a[i-1]);
}

void InsertSort(LinkList L)
/*鏈式儲存結構下的插入排序*/
{
    ListNode *p=L->next,*pre,*q;
    L->next=NULL;           /*初始時,已排序連結串列為空*/
    while(p!=NULL)          /*p是指向待排序的結點*/
    {
        if(L->next==NULL)   /*如*p是第一個結點,則插入到L,並令已排序的最後一個結點的指標域為空*/
        {
            L->next=p;
            p=p->next;
            L->next->next=NULL;
        }
        else                /*p指向待排序的結點,在L指向的已經排好序的連結串列中查詢插入位置*/
        {
            pre=L;
            q=L->next;  
            while(q!=NULL&&q->data<p->data) /*在q指向的有序表中尋找插入位置*/
            {
                pre=q;
                q=q->next; 
            }
            q=p->next;                      /*q指向p的下一個結點,儲存待排序的指標位置*/
            p->next=pre->next;              /*將結點*p插入到結點*pre的後面*/
            pre->next=p;
            p=q;                            /*p指向下一個待排序的結點*/
        }
    }
}
void main()
{
    LinkList L,p;
    int n=8;
    DataType a[]={76,55,10,21,65,90,5,38};
    InitList(&L);
    CreateList(L,a,n);
    printf("排序前的元素序列:\n");
    for(p=L->next;p!=NULL;p=p->next)
        printf("%4d ",p->data);
    printf("\n");
    InsertSort(L);
    printf("排序後的元素序列:\n");
    for(p=L->next;p!=NULL;p=p->next)
        printf("%4d ",p->data);
    printf("\n");
}

相關文章